sl@0: // (C) Copyright Jonathan Turkanis 2003. sl@0: // Distributed under the Boost Software License, Version 1.0. (See accompanying sl@0: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.) sl@0: sl@0: // See http://www.boost.org/libs/iostreams for documentation. sl@0: sl@0: #ifndef BOOST_IOSTREAMS_INVERT_HPP_INCLUDED sl@0: #define BOOST_IOSTREAMS_INVERT_HPP_INCLUDED sl@0: sl@0: #if defined(_MSC_VER) && (_MSC_VER >= 1020) sl@0: # pragma once sl@0: #endif sl@0: sl@0: #include // copy, min. sl@0: #include sl@0: #include // BOOST_DEDUCED_TYPENAME. sl@0: #include // default_filter_buffer_size. sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: // Must come last. sl@0: #include // MSVC. sl@0: sl@0: namespace boost { namespace iostreams { sl@0: sl@0: // sl@0: // Template name: inverse. sl@0: // Template paramters: sl@0: // Filter - A filter adapter which sl@0: // Description: Returns an instance of an appropriate specialization of inverse. sl@0: // sl@0: template sl@0: class inverse { sl@0: private: sl@0: typedef typename category_of::type base_category; sl@0: typedef reference_wrapper filter_ref; sl@0: public: sl@0: typedef typename char_type_of::type char_type; sl@0: typedef typename int_type_of::type int_type; sl@0: typedef char_traits traits_type; sl@0: typedef typename sl@0: mpl::if_< sl@0: is_convertible< sl@0: base_category, sl@0: input sl@0: >, sl@0: output, sl@0: input sl@0: >::type mode; sl@0: struct category sl@0: : mode, sl@0: filter_tag, sl@0: multichar_tag, sl@0: closable_tag sl@0: { }; sl@0: explicit inverse( const Filter& filter, sl@0: std::streamsize buffer_size = sl@0: default_filter_buffer_size) sl@0: : pimpl_(new impl(filter, buffer_size)) sl@0: { } sl@0: sl@0: template sl@0: std::streamsize read(Source& src, char* s, std::streamsize n) sl@0: { sl@0: typedef detail::counted_array_sink array_sink; sl@0: typedef composite filtered_array_sink; sl@0: sl@0: assert((flags() & f_write) == 0); sl@0: if (flags() == 0) { sl@0: flags() = f_read; sl@0: buf().set(0, 0); sl@0: } sl@0: sl@0: filtered_array_sink snk(filter(), array_sink(s, n)); sl@0: int_type status; sl@0: for ( status = traits_type::good(); sl@0: snk.second().count() < n && status == traits_type::good(); ) sl@0: { sl@0: status = buf().fill(src); sl@0: buf().flush(snk); sl@0: } sl@0: return snk.second().count() == 0 && sl@0: status == traits_type::eof() sl@0: ? sl@0: -1 sl@0: : sl@0: snk.second().count(); sl@0: } sl@0: sl@0: template sl@0: std::streamsize write(Sink& dest, const char* s, std::streamsize n) sl@0: { sl@0: typedef detail::counted_array_source array_source; sl@0: typedef composite filtered_array_source; sl@0: sl@0: assert((flags() & f_read) == 0); sl@0: if (flags() == 0) { sl@0: flags() = f_write; sl@0: buf().set(0, 0); sl@0: } sl@0: sl@0: filtered_array_source src(filter(), array_source(s, n)); sl@0: for (bool good = true; src.second().count() < n && good; ) { sl@0: buf().fill(src); sl@0: good = buf().flush(dest); sl@0: } sl@0: return src.second().count(); sl@0: } sl@0: sl@0: template sl@0: void close( Device& dev, sl@0: BOOST_IOS::openmode which = sl@0: BOOST_IOS::in | BOOST_IOS::out ) sl@0: { sl@0: if ((which & BOOST_IOS::out) != 0 && (flags() & f_write) != 0) sl@0: buf().flush(dev); sl@0: flags() = 0; sl@0: } sl@0: private: sl@0: filter_ref filter() { return boost::ref(pimpl_->filter_); } sl@0: detail::buffer& buf() { return pimpl_->buf_; } sl@0: int& flags() { return pimpl_->flags_; } sl@0: sl@0: enum flags_ { sl@0: f_read = 1, f_write = 2 sl@0: }; sl@0: sl@0: struct impl { sl@0: impl(const Filter& filter, std::streamsize n) sl@0: : filter_(filter), buf_(n), flags_(0) sl@0: { buf_.set(0, 0); } sl@0: Filter filter_; sl@0: detail::buffer buf_; sl@0: int flags_; sl@0: }; sl@0: shared_ptr pimpl_; sl@0: }; sl@0: sl@0: // sl@0: // Template name: invert. sl@0: // Template paramters: sl@0: // Filter - A model of InputFilter or OutputFilter. sl@0: // Description: Returns an instance of an appropriate specialization of inverse. sl@0: // sl@0: template sl@0: inverse invert(const Filter& f) { return inverse(f); } sl@0: sl@0: //----------------------------------------------------------------------------// sl@0: sl@0: } } // End namespaces iostreams, boost. sl@0: sl@0: #include // MSVC. sl@0: sl@0: #endif // #ifndef BOOST_IOSTREAMS_INVERT_HPP_INCLUDED