File indexing completed on 2025-01-30 09:44:30
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED
0009 #define BOOST_IOSTREAMS_AGGREGATE_FILTER_HPP_INCLUDED
0010
0011 #if defined(_MSC_VER)
0012 # pragma once
0013 #endif
0014
0015 #include <algorithm> // copy, min.
0016 #include <boost/assert.hpp>
0017 #include <iterator> // back_inserter
0018 #include <vector>
0019 #include <boost/iostreams/constants.hpp> // default_device_buffer_size
0020 #include <boost/iostreams/categories.hpp>
0021 #include <boost/iostreams/detail/char_traits.hpp>
0022 #include <boost/iostreams/detail/ios.hpp> // openmode, streamsize.
0023 #include <boost/iostreams/pipeline.hpp>
0024 #include <boost/iostreams/read.hpp> // check_eof
0025 #include <boost/iostreams/write.hpp>
0026 #include <boost/mpl/bool.hpp>
0027 #include <boost/type_traits/is_convertible.hpp>
0028
0029
0030 #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC.
0031
0032 namespace boost { namespace iostreams {
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 template<typename Ch, typename Alloc = std::allocator<Ch> >
0045 class aggregate_filter {
0046 public:
0047 typedef Ch char_type;
0048 struct category
0049 : dual_use,
0050 filter_tag,
0051 multichar_tag,
0052 closable_tag
0053 { };
0054 aggregate_filter() : ptr_(0), state_(0) { }
0055 virtual ~aggregate_filter() { }
0056
0057 template<typename Source>
0058 std::streamsize read(Source& src, char_type* s, std::streamsize n)
0059 {
0060 using namespace std;
0061 BOOST_ASSERT(!(state_ & f_write));
0062 state_ |= f_read;
0063 if (!(state_ & f_eof))
0064 do_read(src);
0065 std::streamsize amt =
0066 (std::min)(n, static_cast<std::streamsize>(data_.size() - ptr_));
0067 if (amt) {
0068 BOOST_IOSTREAMS_CHAR_TRAITS(char_type)::copy(s, &data_[ptr_], amt);
0069 ptr_ += amt;
0070 }
0071 return detail::check_eof(amt);
0072 }
0073
0074 template<typename Sink>
0075 std::streamsize write(Sink&, const char_type* s, std::streamsize n)
0076 {
0077 BOOST_ASSERT(!(state_ & f_read));
0078 state_ |= f_write;
0079 data_.insert(data_.end(), s, s + n);
0080 return n;
0081 }
0082
0083 template<typename Sink>
0084 void close(Sink& sink, BOOST_IOS::openmode which)
0085 {
0086 if ((state_ & f_read) != 0 && which == BOOST_IOS::in)
0087 close_impl();
0088 if ((state_ & f_write) != 0 && which == BOOST_IOS::out) {
0089 try {
0090 vector_type filtered;
0091 do_filter(data_, filtered);
0092 do_write(
0093 sink, &filtered[0],
0094 static_cast<std::streamsize>(filtered.size())
0095 );
0096 } catch (...) {
0097 close_impl();
0098 throw;
0099 }
0100 close_impl();
0101 }
0102 }
0103
0104 protected:
0105 typedef std::vector<Ch, Alloc> vector_type;
0106 typedef typename vector_type::size_type size_type;
0107 private:
0108 virtual void do_filter(const vector_type& src, vector_type& dest) = 0;
0109 virtual void do_close() { }
0110
0111 template<typename Source>
0112 void do_read(Source& src)
0113 {
0114 using std::streamsize;
0115 vector_type data;
0116 while (true) {
0117 const std::streamsize size = default_device_buffer_size;
0118 Ch buf[size];
0119 std::streamsize amt;
0120 if ((amt = boost::iostreams::read(src, buf, size)) == -1)
0121 break;
0122 data.insert(data.end(), buf, buf + amt);
0123 }
0124 do_filter(data, data_);
0125 state_ |= f_eof;
0126 }
0127
0128 template<typename Sink>
0129 void do_write(Sink& sink, const char_type* s, std::streamsize n)
0130 {
0131 typedef typename iostreams::category_of<Sink>::type category;
0132 typedef is_convertible<category, output> can_write;
0133 do_write(sink, s, n, can_write());
0134 }
0135
0136 template<typename Sink>
0137 void do_write(Sink& sink, const char_type* s, std::streamsize n, mpl::true_)
0138 { iostreams::write(sink, s, n); }
0139
0140 template<typename Sink>
0141 void do_write(Sink&, const char_type*, std::streamsize, mpl::false_) { }
0142
0143 void close_impl()
0144 {
0145 data_.clear();
0146 ptr_ = 0;
0147 state_ = 0;
0148 do_close();
0149 }
0150
0151 enum flag_type {
0152 f_read = 1,
0153 f_write = f_read << 1,
0154 f_eof = f_write << 1
0155 };
0156
0157
0158 vector_type data_;
0159 size_type ptr_;
0160 int state_;
0161 };
0162 BOOST_IOSTREAMS_PIPABLE(aggregate_filter, 1)
0163
0164 } }
0165
0166 #include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC.
0167
0168 #endif