Rogue Wave banner
Previous fileTop of DocumentContentsIndexNext file

18.2 Deriving New Stream Buffer Classes

Deriving a new streambuf class is not commonly necessary, but it can be extraordinarily useful when specialized behavior is needed. For example, consider a log book stream that starts writing at the beginning after reaching a certain size, so that the log file does not grow infinitely. In order to implement this new class, we first need to derive a new stream buffer type. The easiest way to do this is to derive from filebuf, and then reimplement one of the protected virtual functions:

//1All streams should have these types defined.
//2This constructor takes a size parameter that we'll use to limit the size of the log file.
//3The protected virtual function overflow(char_type) is called whenever a stream attempts to write to the stream buffer when the put area is full. We re-implement the function in order to reset the file pointer to the beginning whenever the file gets too large.

The overflow function is implemented as follows:

//1First, retain the size of the put area of the buffer in a local variable. Both epptr() and pbase() are protected functions in basic_streambuf that return, respectively, the beginning and end of the put area. Other protected functions return the beginning and end of the get area, and also the current get and put positions. See the Class Reference for a full description of these functions.
//2Next, call filebuf's ovrflow to write the put area of the buffer out to the file.
//3Now use seekoff to get the current stream position and see if the distance between that and our maximum file size is less than the size of the put buffer. If it is, the next flush of the put area will exceed the maximum size we've set for the file.
//4Seek back to the beginning of the stream(file) when the log is getting too large. Future writes to the stream will overwrite the contents of the log file starting at the beginning.
//5Finally, return the value we got from filebuf's overflow function.

In order to use this new logbuf class, we'll also need a new logstream class:

//1This private member provides us with a logbuffer object.
//2Again, we want to define the standard set of types.
//3This constructor creates a stream with the given maximum size and the given file name.
//4rdbuf returns a pointer to the logbuffer.

Finally, we implement our new log stream class as shown here:

//1The ios_base::init() function initializes the base class. In part the initialization consists of installing a pointer to the logbuffer in the ios_base so base classes have access to the buffer.
//2Open the file for writing.
//3Always start out writing at the beginning.

We can use this new log buffer class as follows:

//1Create a logstream object with a maximum size of 4000 characters and attach it to the file test.log.
//2Write out the integers from 0 to 999 to the log file. The total number of characters required to represent these numbers along with the spaces between them will exceed the maximum size we've set.
//3Seek to the beginning of the file.
//4Look at the first value in the file. If we had used an ordinary fstream then this value would be 0, the first value we wrote out. Instead, we used a logstream and wrote out more than the log can hold, so we'll get a different number since the log has wrapped around to the beginning.

Previous fileTop of DocumentContentsIndexNext file

OEM Edition, ©Copyright 1999, Rogue Wave Software, Inc.
Contact Rogue Wave about documentation or support issues.