TITLE: stream underflow, overflow, and filtering (Newsgroups: comp.lang.c++.moderated, 19 Sept 97) GREGORY: "Alastair Gregory" |> I am trying to Overload the Overflow and Underflow functions in |> streambuf (Borland 4 implementation). The problem I am having is |> understanding the implementation of the buffer. |> |> I belive that the stream buf class has bean defined inorder for |> these functions to be Overriden but I cant find any information |> on what has to be done. KANZE: kanze@gabi-soft.fr (J. Kanze) Your impression is correct. This is precisely the role of streambuf -- provide an interface, for the user (derived class) to implement. GREGORY: |> I am trying to add a line counter to the existing stream functions . |> Later I which to also add an input filter (Eg striping out of 'C' |> type comments). I think Overloading the Overflow and Underflow |> functions is the way to go KANZE: The basic rules are easy (sort of): overflow: This function is called on output, when there is no buffer, or no space in the existing buffer. If you want buffering, the buffer should be set up in the first call to overflow. The argument is the character to be output, or EOF. For historical reasons, it is probably advisable to call sync on EOF. The exact functionality of this function will depend on the buffering strategy used. Without buffering, just output the argument, returning the character output, or EOF on error. With buffering: if there is no buffer, create one, otherwise flush it, and insert the character into the buffer. (Use the function setp to initialize the buffer, or to reset it to empty once you've flushed it, and the functions gptr and egptr to get the current values.) underflow: This function is called on input, which is a little more complicated. In particular, although the function returns the next character in the stream, it does *not* extract it from the stream. Input *must* be buffered, although a one character buffer is sufficient. Also, there is no guarantee that the get buffer will be empty when this function is called, so you have to check that. In all cases, when you return, 1) the next character must be present in the buffer -- if there wasn't a buffer before, you have to create one, and 2) that character must be returned. You must overload both of these functions, even if the stream is unidirectional. (Overload the one you're not interested in to just return EOF.) Also, you will probably need to overload sync, and perhaps setbuf. Finally, for things like stripping out comments, I would use something I call a filtering streambuf. This is a streambuf which contains a pointer to another streambuf, which is uses as the actual sink or source. I do this a lot -- often enough, in fact, that I have a template class which handles the boilerplating, and is instantiated over a class which handles just the actual filtering. Thus, to strip out shell type comments (single charater, to end of line), all I have to write is: #include template< char commentChar > struct UncommentExtractor { int extract( streambuf* sb ) { int ch( sb->sbumpc() ) ; if ( ch == commentChar ) { while ( ch != EOF && ch != '\n' ) ch = sb->sbumpc() ; } return ch ; } void finalize( streambuf* ) { } } ; FilteringIstream< UncommentExtractor< '#' > > in( cin ) ; If anyone wishes a copy of these templates, just drop me an email, and I'll send it to you (tar'ed, gzip'ed and uuencoded).