Path: utzoo!attcan!uunet!aplcen!uakari.primate.wisc.edu!zaphod.mps.ohio-state.edu!mips!ardent!jra!jss From: jss@jra.ardent.com Newsgroups: comp.lang.c++ Subject: Re: Newline hook needed in streams Message-ID: <9804@ardent.UUCP> Date: 21 Dec 89 19:12:05 GMT References: <1989Dec18.132745.5187@odi.com> Sender: news@ardent.UUCP Reply-To: jss@jra.ardent.com () Organization: Ardent Computer Corp., Sunnyvale, CA Lines: 63 In article <1989Dec18.132745.5187@odi.com> benson@odi.com (Benson I. Margulies) writes: >I've needed to implement two special kinds of ostreams that seem to >need "line buffering" support. That is, I need to have code of mine >get control (via virtual function or function pointer) whenever >a newline is inserted into the buffer. > >The two examples are an indenting stream (add a settable amount >of indentation to the left margin) and a syslog stream. >The indenting stream needs to know newline boundaries to know >when to insert the indentation. The syslog stream wants to >actually call syslog(3) for each line of output. > This request came up a lot while I was designing iostreams, but I was never able to solve the fundamental problem that doing line bufferring required some action on every character to check if it is a newline and (since there are already complaints about the amount of code inlined by put) would amount to making the stream unbuffered. That does not mean there is no way to solve the problems, but it means you have to do some extra work. I will describe one approach that I have found useful. First, the easiest place to do this kind of thing is in the streambuf, rather than the ostream class. What I have typically done is derive a new class from filebuf with a redefined "flush" member. This member does whatever extra processing it required and then call filebuf::flush to really output the data. This approach will probably be sufficient for the syslog. For an indenting ostream this is not adequate since some means is probably required to tell the streambuf the current indent The amount ought to be kept as formatting information associated with the ostream (use xalloc and iword) and passed on to the streambuf as appropriate (presumably using a member function). Also it is a bit restrictive to assume that the indenting can only be done on a file, so rather than deriveng a new class derived from filebuf, it might be better to have a more general approach that would allow indenting to be inserted between the ostream and an abritrary streambuf. I'd be interested to hear from anybody who has written this kind of streambuf class about what approaches they have taken. Some easily overlooked parts of the iostream library that are relevant to these problems. There is a "unitbuf" flag in the ios interface. When this is set it causes flush() to be called frequently (although not on every character). There is an ostream constructor that takes an explicit streambuf as an argument. It is therefore not necessary to declare a new ostream class in order to use a streambuf that does something special. streambuf::flush is not required to consume data. If it is called while there is still room for more characters in the arrays it can return without doing anything. Jerry Schwarz jss@ardent.com