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