Copyright (C) 1993 Free Software Foundation, Inc.
The author of this software is David M. Gay.
Copyright (c) 1991 by AT&T.
Permission to use, copy, modify, and distribute this software for any purpose without fee is hereby granted, provided that this entire notice is included in all copies of any software which is or includes a copy or modification of this software and in all copies of the supporting documentation for such software.
THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
streambuf
LayerThe istream and ostream classes are meant to handle conversion between objects in the program and their textual representation.
By contrast, the underlying streambuf class is for transferring raw bytes between the program, and input sources or output sinks. Different streambuf subclasses connect to different kinds of sources and sinks.
streambuf
Streambuf buffer management is fairly sophisticated (this is a nice way to say "complicated"). The standard protocol has the following "areas":
The following methods are used to manipulate these areas. These are all protected methods, which are intended to be used by virtual function in classes derived from streambuf. They are also all ANSI/ISO-standard.
Note: If a pointer points to the 'end' of an area, it means that it points to the character after the area.
overflow
Supposing there is a function write_to_window that writes characters to a window object. To write to it using the ostream function,here is one (portable) way to do it. This depends on the default buffering (if any).
#include <iostream.h> /* Returns number of characters successfully written to win. */ extern int write_to_window (window* win, char* text, int length); class windowbuf : public streambuf { window* win; public: windowbuf (window* w) { win = w; } int sync (); int overflow (int ch); // Defining xsputn is an optional optimization. // (streamsize was recently added to ANSI C++, not portable yet.) streamsize xsputn (char* text, streamsize n); }; int windowbuf::sync () { streamsize n = pptr () - pbase (); return (n && write_to_window (win, pbase (), n) != n) ? EOF : 0; } int windowbuf::overflow (int ch) { streamsize n = pptr () - pbase (); if (n && sync ()) return EOF; if (ch != EOF) { char cbuf[1]; cbuf[0] = ch; if (write_to_window (win, cbuf, 1) != 1) return EOF; } pbump (-n); // Reset pptr(). return 0; } streamsize windowbuf::xsputn (char* text, streamsize n) { return sync () == EOF ? 0 : write_to_window (win, text, n); } int main (int argc, char**argv) { window *win = ...; windowbuf wbuf(win); ostream wstr(&wbuf); wstr << "Hello world!\n"; }
streambuf
objects
stdio
A stdiobuf is a streambuf object that points to a FILE object (as defined by stdio.h). All streambuf operations on the stdiobuf are forwarded to the FILE. Thus the stdiobuf object provides a wrapper around a FILE, allowing use of streambuf operations on a FILE. This can be useful when mixing C code with C++ code.
The pre-defined streams cin, cout, and cerr are normally implemented as stdiobuf objects that point to respectively stdin, stdout, and stderr. This is convenient, but it does cost some extra overhead.
If things are set up to use the implementation of stdio provided with this library, then cin, cout, and cerr will be set up to to use stdiobuf objects, since their benefits are obtained for free. See C Input and Output.
The procbuf class is an extension that is derived from streambuf. A procbuf can be closed (in which case it does nothing), or open (in which case it allows communicating through a pipe with some other program).
If mode is `ios::in', standard output from the program is sent to a pipe; read from the pipe by reading from the procbuf. (This is similar to `popen(command, "r")'.)
If mode is `ios::out', output written written to the procbuf is written to a pipe; the program is set up to read its standard input from (the other end of) the pipe. (This is similar to `popen(command, "w")'.)
The procbuf must start out in the closed state. Returns `*this' on success, and `NULL' on failure.
The STL port library allows the user to ask a streambuf to remember the current position. This allows the user to go back to this position later, after reading further. The user can back up arbitrary amounts, even on unbuffered files or multiple buffers' worth, as long as the library is informed in advance. This unbounded backup is very useful for scanning and parsing applications. This example shows a typical scenario:
// Read either "dog", "hound", or "hounddog". // If "dog" is found, return 1. // If "hound" is found, return 2. // If "hounddog" is found, return 3. // If none of these are found, return -1. int my_scan(streambuf* sb) { streammarker fence(sb); char buffer[20]; // Try reading "hounddog": if (sb->sgetn(buffer, 8) == 8 && strncmp(buffer, "hounddog", 8) == 0) return 3; // No, no "hounddog": Back up to 'fence' sb->seekmark(fence); // // ... and try reading "dog": if (sb->sgetn(buffer, 3) == 3 && strncmp(buffer, "dog", 3) == 0) return 1; // No, no "dog" either: Back up to 'fence' sb->seekmark(fence); // // ... and try reading "hound": if (sb->sgetn(buffer, 5) == 5 && strncmp(buffer, "hound", 5) == 0) return 2; // No, no "hound" either: Back up and signal failure. sb->seekmark(fence); // Backup to 'fence' return -1; }
An indirectbuf is one that forwards all of its I/O requests to another streambuf.
An indirectbuf can be used to implement Common Lisp synonym-streams and two-way-streams:
class synonymbuf : public indirectbuf { Symbol *sym; synonymbuf(Symbol *s) { sym = s; } virtual streambuf *lookup_stream(int mode) { return coerce_to_streambuf(lookup_value(sym)); } };
|