The class IFilterBuf was designed with the openSSL BIO (cf. bio(3ssl)) in mind. Since the BIO concept was developed in the context of the C programming language, BIOs do not support C++ streams. Nonetheless, the concept of a filtering device is an attractive one, and is offered by the FBB::IFilterBuf class.
In addition to filtering, IFilterBuf offers flexible internal buffer management: derived classes can push back characters until the beginning of the internal buffer has been reached, but may then continue pushing back characters until the internal buffer has reached its maximum size. This maximum size is defined by the constructor's maxSize parameter (see below).
The class IFilterBuf is an abstract base class. It is used via classes that are derived from IFilterBuf, implementing its pure virtual load member (see below at PRIVATE VIRTUAL MEMBER FUNCTIONS).
Copy and move constructors (and assignment operators) are not available.
Derived classes do not have to call this member, but if they do they should only call setBuffer once from their constructors. Once setBuffer has been called, the peek member of the std::istream that is available to IFilterBuf objects can be called to inspect the next available character, even if no other stream operation has as yet been performed. If it is not called by the derived class's constructor, then peek returns 0 until at least one character has been retrieved from the istream object.
Derived class objects are responsible for obtaining information (in any amount) from the device with which they interact. This information is then passed on to the IFilterBuf via two pointers, pointing, respectively, to the first available character and beyond the last available character. The characters indicated by this range are subsequently transferred by the IFilterBuf object to its own buffer, from where they are then retrieved (or to where they can be pushed back) by the application.
The filter member allows implementations to filter and/or modify the information that is obtained by this member. The EXAMPLE section below provides an example filtering out a configurable set of characters from a provided std::istream. Bobcat's classes ISymCryptStreambuf(3bobcat) and IBase64Buf(3bobcat) provide additional examples of classes derived from IFilterBuf.
The filter member should return false if no (more) information is available. It should return true if information is available, in which case *srcBegin and *srcEnd should be pointing to, respectively, the first character and beyond the last character made available by filter;
Here is a class, derived from IFilterBuf, filtering out a predefined set of characters. It is used twice to filter digits and vowels, illustrating chaining of IFilterBuf objects.
#include <iostream> #include <istream> #include <string> #include <bobcat/ifilterbuf> class CharFilterStreambuf: public FBB::IFilterBuf { std::istream &d_in; // stream to read from std::string d_rmChars; // chars to rm std::string d_buffer; // locally buffered chars size_t const d_maxSize = 100; public: CharFilterStreambuf(std::istream &in, std::string const &rmChars); private: bool filter(char const **srcBegin, char const **srcEnd) override; }; CharFilterStreambuf::CharFilterStreambuf(std::istream &in, std::string const &rmChars) : d_in(in), d_rmChars(rmChars) { setBuffer(); // required if peek() must return the 1st } // available character right from the start bool CharFilterStreambuf::filter(char const **srcBegin, char const **srcEnd) { d_buffer.clear(); while (d_buffer.size() != d_maxSize) { char ch; if (not d_in.get(ch)) break; if (d_rmChars.find(ch) != std::string::npos) // found char to rm continue; d_buffer.push_back(ch); } if (d_buffer.empty()) return false; *srcBegin = d_buffer.data(); *srcEnd = d_buffer.data() + d_buffer.size(); return true; } int main() { CharFilterStreambuf buf1(std::cin, "1234567890"); std::istream in1(&buf1); CharFilterStreambuf buf2(in1, "AEIOUaeiou"); std::istream in2(&buf2); std::cout << in2.rdbuf(); }