Tutorial

2.2.9. Dual-Use Filters

It can be confusing to maintain two separate filters — one for input and the other for output — to implement the same filtering algorithm. One way to avoid this is to use the filter helpers mentioned above. The filter helpers produce filters which can be used for either input or output, but not both simultaneously. Such filters are called Dual-Use Filters.

A Dual-Use Filter can be produced by merging the implementations of an InputFilter and an OutputFilter, and giving the resulting class a category convertible to dual_use_filter_tag. For example, you can implement a shell comments Filter as a Dual-Use Filter as follows:

#include <boost/iostreams/char_traits.hpp> // EOF, WOULD_BLOCK
#include <boost/iostreams/concepts.hpp>    // input_filter
#include <boost/iostreams/operations.hpp>  // get

namespace boost { namespace iostreams { namespace example {

class shell_comments_input_filter : public dual_use_filter {
public:
    explicit shell_comments_input_filter(char comment_char = '#')
        : comment_char_(comment_char), skip_(false)
        { }

    template<typename Source>
    int get(Source& src)
    {
        /* same as shell_comments_input_filter::get() */
    }

    template<typename Sink>
    bool put(Sink& dest, int c)
    {
        /* same as shell_comments_output_filter::put() */
    }

    template<typename Device>
    void close(Device&, std::ios_base::openmode)
    { 
        skip_ = false; 
    }
private:
    char comment_char_;
    bool skip_;
};

} } } // End namespace boost::iostreams:example

When a filtering stream or stream buffer containing a Closable Dual-Use Filter is closed, the Filter's member function close is called with one of the values std::ios_base::in or std::ios_base::out as the second function argument, indicating whether the Filter was used for input or output.