File indexing completed on 2025-01-30 09:44:33
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_IOSTREAMS_INVERT_HPP_INCLUDED
0009 #define BOOST_IOSTREAMS_INVERT_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 <boost/config.hpp> // BOOST_DEDUCED_TYPENAME.
0018 #include <boost/detail/workaround.hpp> // default_filter_buffer_size.
0019 #include <boost/iostreams/char_traits.hpp>
0020 #include <boost/iostreams/compose.hpp>
0021 #include <boost/iostreams/constants.hpp>
0022 #include <boost/iostreams/device/array.hpp>
0023 #include <boost/iostreams/detail/buffer.hpp>
0024 #include <boost/iostreams/detail/counted_array.hpp>
0025 #include <boost/iostreams/detail/execute.hpp>
0026 #include <boost/iostreams/detail/functional.hpp> // clear_flags, call_reset
0027 #include <boost/mpl/if.hpp>
0028 #include <boost/ref.hpp>
0029 #include <boost/shared_ptr.hpp>
0030 #include <boost/type_traits/is_convertible.hpp>
0031
0032
0033 #include <boost/iostreams/detail/config/disable_warnings.hpp> // MSVC.
0034
0035 namespace boost { namespace iostreams {
0036
0037
0038
0039
0040
0041
0042
0043
0044 template<typename Filter>
0045 class inverse {
0046 private:
0047 BOOST_STATIC_ASSERT(is_filter<Filter>::value);
0048 typedef typename category_of<Filter>::type base_category;
0049 typedef reference_wrapper<Filter> filter_ref;
0050 public:
0051 typedef typename char_type_of<Filter>::type char_type;
0052 typedef typename int_type_of<Filter>::type int_type;
0053 typedef char_traits<char_type> traits_type;
0054 typedef typename
0055 mpl::if_<
0056 is_convertible<
0057 base_category,
0058 input
0059 >,
0060 output,
0061 input
0062 >::type mode;
0063 struct category
0064 : mode,
0065 filter_tag,
0066 multichar_tag,
0067 closable_tag
0068 { };
0069 explicit inverse( const Filter& filter,
0070 std::streamsize buffer_size =
0071 default_filter_buffer_size)
0072 : pimpl_(new impl(filter, buffer_size))
0073 { }
0074
0075 template<typename Source>
0076 std::streamsize read(Source& src, char_type* s, std::streamsize n)
0077 {
0078 typedef detail::counted_array_sink<char_type> array_sink;
0079 typedef composite<filter_ref, array_sink> filtered_array_sink;
0080
0081 BOOST_ASSERT((flags() & f_write) == 0);
0082 if (flags() == 0) {
0083 flags() = f_read;
0084 buf().set(0, 0);
0085 }
0086
0087 filtered_array_sink snk(filter(), array_sink(s, n));
0088 int_type status;
0089 for ( status = traits_type::good();
0090 snk.second().count() < n && status == traits_type::good(); )
0091 {
0092 status = buf().fill(src);
0093 buf().flush(snk);
0094 }
0095 return snk.second().count() == 0 &&
0096 status == traits_type::eof()
0097 ?
0098 -1
0099 :
0100 snk.second().count();
0101 }
0102
0103 template<typename Sink>
0104 std::streamsize write(Sink& dest, const char_type* s, std::streamsize n)
0105 {
0106 typedef detail::counted_array_source<char_type> array_source;
0107 typedef composite<filter_ref, array_source> filtered_array_source;
0108
0109 BOOST_ASSERT((flags() & f_read) == 0);
0110 if (flags() == 0) {
0111 flags() = f_write;
0112 buf().set(0, 0);
0113 }
0114
0115 filtered_array_source src(filter(), array_source(s, n));
0116 for (bool good = true; src.second().count() < n && good; ) {
0117 buf().fill(src);
0118 good = buf().flush(dest);
0119 }
0120 return src.second().count();
0121 }
0122
0123 template<typename Device>
0124 void close(Device& dev)
0125 {
0126 detail::execute_all(
0127 detail::flush_buffer(buf(), dev, (flags() & f_write) != 0),
0128 detail::call_close_all(pimpl_->filter_, dev),
0129 detail::clear_flags(flags())
0130 );
0131 }
0132 private:
0133 filter_ref filter() { return boost::ref(pimpl_->filter_); }
0134 detail::buffer<char_type>& buf() { return pimpl_->buf_; }
0135 int& flags() { return pimpl_->flags_; }
0136
0137 enum flags_ {
0138 f_read = 1, f_write = 2
0139 };
0140
0141 struct impl {
0142 impl(const Filter& filter, std::streamsize n)
0143 : filter_(filter), buf_(n), flags_(0)
0144 { buf_.set(0, 0); }
0145 Filter filter_;
0146 detail::buffer<char_type> buf_;
0147 int flags_;
0148 };
0149 shared_ptr<impl> pimpl_;
0150 };
0151
0152
0153
0154
0155
0156
0157
0158 template<typename Filter>
0159 inverse<Filter> invert(const Filter& f) { return inverse<Filter>(f); }
0160
0161
0162
0163 } }
0164
0165 #include <boost/iostreams/detail/config/enable_warnings.hpp> // MSVC.
0166
0167 #endif