TIP: Click on subject to list as thread! ANSI
echo: aust_c_here
to: Greg Newton
from: David Nugent
date: 1995-04-06 14:08:50
subject: C++ Streams as Filters?

> I have been contemplating the writing of filters using C++
 > streams, or more precisely C++ streams that act as filters,
 > and am completely bamboozled as to how to go about it.  The
 > end result that I'd like to achieve is something like:

 > // Detab.cc
 > int main( ...

 >    MyDetabbingOutputStream ostr;    // default constructor...
 >                                     // other constructors as per fstreams

 >         if( !ostr.open("output.fil","w") )
 >          etc;

 >         ostr << "The quick brown\tfox jumps\tover the lazy
dog.";

 > ///////////////////////

 > and the result in "output.fil" to be

 > "The quick brown        fox jumps       over the lazy dog."
 >                 ^^^^^^^^         ^^^^^^^
 >                 |                |
 > spaces----------+----------------+

Ok. This isn't what I'd call a "filter" though. A filter, in the
classic sense, is one that takes input from stdin, does something to it,
and sends output to stdout.

 > My quandary: is it possible to simply derive my stream class
 > from existing streams, and somehow stipulate that all output
 > passes through (so to speak) my output filter (and if so,
 > HOW??), or do I need to go right back to streambuf level, and
 > derive a sort of 'parallel' hierarchy to the existing
 > iostream and fstream, rewriting all members that write to the
 > streambuf so that they are 'filtered' as required.  This
 > second option seems unnecessarily complicated to me, but I
 > can't see how to achieve the first.

Actually, doing this is not nearly as "unnecessarily complicated"
as it seems. The problem is that iostreams in general has very poor
documentation. There are exceptions, but most of what you find in your
compiler manuals are derived first or second level from the AT&T
reference manuals, which are *awful*.

The iostreams class hierachy is there TO BE DERIVED FROM. If you look at
the ios side - where all the 'input' and 'output' come from and go to,
you'll see that these are just convenient front-ends which do formatting
and provide a type-safe front end for the actual streams. The *real* work
is done in streambuf, which is responsible for the buffering and output
itself.


 > This example only refers to ostreams, but I want to do the
 > same for istreams, too.

 > Any suggestions (serious or otherwise :)  welcome.
~
 > PS.   Detabbing in itself isn't the problem, just an illustration of it.

Sure.

I had a reasonably good example of this before a disk crash recently. Oh,
now I come to think of it, you'll find it in the C_ECHO SNIPPETS. It shows
how to derive classes from streambufs for custom I/O source and
destinations - but the same principle applies.

With tab expansion, I probably wouldn't go that far though. If all you want
to do is to expand tabs, then you can do so by defining a custom filebuf
(ie. derive from filebuf), override the virtual function there which
handles the stream on a byte by byte basis (do_sputn()), and expand tabs by
keeping track of the 'current column'.

Of course, for this task it's just as easy to use istream::getline(),
expand the tabs and output to your ostream, but since this is a learning
excercise, we can ignore that. :-)

BTW, you can use an ostream_withassign for your streambuf - this is a
predefined class (and is in fact the class used for cout). To initialise
it, just do:

    main()
    {
        ostream_withassign myout;

        myout=new my_class_derived_from_filebuf(1);

Strangely enough, that's why it's called "ostream_withassign". :)

The significance of the '1' here is to attach the stdout file handle to the
stream. You could just as easily pass a filename and mode to an alternate
constructor.

Hope this helps,

   david

---
* Origin: Unique Computing, Melbourne, Australia (3:632/348)
SEEN-BY: 50/99 620/243 623/630 632/103 348 386 998 633/371 379 634/384 388
SEEN-BY: 635/301 502 503 541 544 727 636/100 639/100 711/401 409 410 430 510
SEEN-BY: 711/807 808 809 932 934 712/515 713/888 714/906 800/1 7877/2809
@PATH: 632/103 348 635/503 50/99 711/808 809 934

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.