1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2003-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
6 // See http://www.boost.org/libs/iostreams for documentation.
8 #ifndef BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED
9 #define BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED
15 #include <algorithm> // copy, min.
16 #include <boost/assert.hpp>
17 #include <iterator> // back_inserter
19 #include <boost/iostreams/constants.hpp> // default_device_buffer_size
20 #include <boost/iostreams/categories.hpp>
21 #include <boost/iostreams/detail/char_traits.hpp>
22 #include <boost/iostreams/detail/ios.hpp> // openmode, streamsize.
23 #include <boost/iostreams/pipeline.hpp>
24 #include <boost/iostreams/read.hpp> // check_eof
25 #include <boost/iostreams/write.hpp>
26 #include <boost/mpl/bool.hpp>
27 #include <boost/type_traits/is_convertible.hpp>
30 #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC.
32 namespace boost { namespace iostreams {
35 // Template name: aggregate_filter.
36 // Template parameters:
37 // Ch - The character type.
38 // Alloc - The allocator type.
39 // Description: Utility for defining DualUseFilters which filter an
40 // entire stream at once. To use, override the protected virtual
42 // Note: This filter should not be copied while it is in use.
44 template<typename Ch, typename Alloc = std::allocator<Ch> >
45 class aggregate_filter {
54 aggregate_filter() : ptr_(0), state_(0) { }
55 virtual ~aggregate_filter() { }
57 template<typename Source>
58 std::streamsize read(Source& src, char_type* s, std::streamsize n)
61 BOOST_ASSERT(!(state_ & f_write));
63 if (!(state_ & f_eof))
66 (std::min)(n, static_cast<std::streamsize>(data_.size() - ptr_));
68 BOOST_IOSTREAMS_CHAR_TRAITS(char_type)::copy(s, &data_[ptr_], amt);
71 return detail::check_eof(amt);
74 template<typename Sink>
75 std::streamsize write(Sink&, const char_type* s, std::streamsize n)
77 BOOST_ASSERT(!(state_ & f_read));
79 data_.insert(data_.end(), s, s + n);
83 template<typename Sink>
84 void close(Sink& sink, BOOST_IOS::openmode which)
86 if ((state_ & f_read) != 0 && which == BOOST_IOS::in)
88 if ((state_ & f_write) != 0 && which == BOOST_IOS::out) {
91 do_filter(data_, filtered);
94 static_cast<std::streamsize>(filtered.size())
105 typedef std::vector<Ch, Alloc> vector_type;
106 typedef typename vector_type::size_type size_type;
108 virtual void do_filter(const vector_type& src, vector_type& dest) = 0;
109 virtual void do_close() { }
111 template<typename Source>
112 void do_read(Source& src)
114 using std::streamsize;
117 const std::streamsize size = default_device_buffer_size;
120 if ((amt = boost::iostreams::read(src, buf, size)) == -1)
122 data.insert(data.end(), buf, buf + amt);
124 do_filter(data, data_);
128 template<typename Sink>
129 void do_write(Sink& sink, const char_type* s, std::streamsize n)
131 typedef typename iostreams::category_of<Sink>::type category;
132 typedef is_convertible<category, output> can_write;
133 do_write(sink, s, n, can_write());
136 template<typename Sink>
137 void do_write(Sink& sink, const char_type* s, std::streamsize n, mpl::true_)
138 { iostreams::write(sink, s, n); }
140 template<typename Sink>
141 void do_write(Sink&, const char_type*, std::streamsize, mpl::false_) { }
153 f_write = f_read << 1,
157 // Note: typically will not be copied while vector contains data.
162 BOOST_IOSTREAMS_PIPABLE(aggregate_filter, 1)
164 } } // End namespaces iostreams, boost.
166 #include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC.
168 #endif // #ifndef BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED