NAME
sbufprot - protected interface of the stream buffer base
class
SYNOPSIS
#include <iostream.h>
typedef long streampos;
typedef long streamoff;
class ios : virtual public unsafe_ios, public stream_MT {
public:
enum open_mode {
in = 0x01, // open for reading
out = 0x02, // open for writing
ate = 0x04, // seek to eof upon original open
app = 0x08, // append mode: all additions at eof
trunc = 0x10, // truncate file if already exists
nocreate = 0x20, // open fails if file doesn't exist
noreplace= 0x40 // open fails if file already exists
};
// stream seek direction
enum seek_dir { beg=0, cur=1, end=2 };
// see ios(3CC4) for remainder ...
} ;
class streambuf : public stream_MT {
public:
streambuf() ;
streambuf(char* p, int len);
void dbp() ;
protected:
int allocate();
char* base();
int blen();
char* eback();
char* ebuf();
char* egptr();
char* epptr();
void gbump(int n);
char* gptr();
char* pbase();
void pbump(int n);
char* pptr();
void setg(char* eb, char* g, char* eg);
void setp(char* p, char* ep);
void setb(char* b, char* eb, int a=0);
int unbuffered();
void unbuffered(int);
virtual int doallocate();
virtual ~streambuf() ;
int allocate_unlocked();
char* base_unlocked();
int blen_unlocked();
char* eback_unlocked();
char* ebuf_unlocked();
char* egptr_unlocked();
char* epptr_unlocked();
void gbump_unlocked(int n);
char* gptr_unlocked();
char* pbase_unlocked();
void pbump_unlocked(int n);
char* pptr_unlocked();
void setg_unlocked(char* eb, char* g, char* eg);
void setp_unlocked(char* p, char* ep);
int unbuffered_unlocked();
void unbuffered_unlocked(int);
public:
virtual int pbackfail(int c);
virtual int overflow(int c=EOF);
virtual int underflow();
virtual streambuf*
setbuf(char* p, int len);
streambuf*
setbuf(unsigned char* p, in len);
virtual streampos
seekpos(streampos, int =ios::in|ios:out);
virtual streampos
seekoff(streamoff, seek_dir, int =ios::in|ios:out);
virtual int sync();
};
DESCRIPTION
The public interface of streambufs is described in
sbufpub(3CC4). Here we discuss the protected interface,
necessary to derive a usable buffer class. The streambuf
class is intended only to be a base class; no streambuf
object is intended to be constructed. Three predefined
derived buffer classes are provided; see filebuf(3CC4),
ssbuf(3CC4), stdiobuf(3CC4).
Generally speaking, the non-virtual functions described here
are not intended to be over-ridden; they provide low-level
buffer-management functions.
We describe virtual functions here in terms of their func-
tionality, and their default behavior. Where the default
behavior is suitable for a derived buffer class, the func-
tion need not be overridden. For example, a buffer class
which has no input source need not do anything on underflow
except return EOF, the default behavior. Where the default
behavior is not appropriate, a class-specific version of the
function should be provided. For example, an input buffer
connected to a file should attempt to read more data on
underflow. A replacement virtual function should conform to
the specification given for the streambuf version to ensure
that other functions which depend on this behavior will con-
tinue to work.
Each of the protected member functions of streambuf uses
locking to help in making streambuf work correctly in a
multi-threaded environment.
A set of unlocked functions are provided that do not imple-
ment the locking associated with making streambuf MT safe.
These functions are distinguished by the suffix _unlocked
appended to the function name.
Constructors and assignment
streambuf()
This constructor creates an empty buffer for an empty
input stream.
streambuf(ptr, len)
This constructor creates an empty buffer, or reserve
area (see below) using the len bytes beginning at the
location pointed to by ptr.
streambuf(streambuf&) // private
operator= (streambuf&) // private
The copy constructor and assignment operator are
private and not implemented to ensure that a streambuf
cannot be copied. You don't want to copy a streambuf,
but rather pass around pointers to one.
The get, put, and reserve areas
The buffer of a streambuf may be considered to have three
parts: the get area, the put area, and the reserve area
(which is the same as the buffer area). The get area con-
tains the characters immediately available for input. The
put area holds characters stored for output but not yet con-
sumed by (flushed to) their ultimate destination. The get
and put areas may be disjoint or may overlap. The reserve
area is the entire buffer, overlapped by the get and put
areas. The get and put areas may expand into the remainder
of the reserve area. In the course of input and output
operations, the sizes of the get and put areas expand and
shrink, always bounded by the total buffer size.
The buffer and its areas are defined by private pointer
variables which may be read and set via protected member
functions. The pointers, described below, should be thought
of as pointing between characters; that is, although a
pointer points ``at'' a character, it is more helpful to
view it as pointing ``just before'' it. This establishes a
correspondence to the abstraction described in
sbufpub(3CC4),
Non-virtual functions for examining pointers
char* ptr = sbuf.base()
Returns a pointer to the beginning of the reserve area.
char* ptr = sbuf.ebuf()
Returns a pointer just past the end of the reserve
area. The space from base() through ebuf()-1 is the
reserve area. If ebuf()==base(), the stream is unbuf-
fered.
char* ptr = sbuf.gptr()
Returns a pointer to the beginning of the get area, and
thus to the next character to be fetched (if there are
any). The characters immediately available are from
gptr() through egptr()-1. If egptr()<=gptr(), no char-
acters are available.
char* ptr = sbuf.egptr()
Returns a pointer just past the end of the get area,
the maximum possible value for gptr().
char* ptr = sbuf.eback()
Returns the lowest possible value for gptr(). The
space from eback() through gptr()-1 is available for
putting characters back (backing up the get pointer).
If eback()==gptr(), an attempted putback operation
might fail.
char* ptr = sbuf.pptr()
Returns a pointer to the beginning of the put area, and
thus to the location of the next character that is
stored (if possible).
char* ptr = sbuf.pbase()
Returns the a pointer to the beginning of the space
available for the put area, the lowest possible value
for pptr(). The area from pbase() through pptr()-1
represents characters which have been stored in the
buffer but not yet consumed.
char* ptr = sbuf.epptr()
Returns a pointer just past the end of the put area,
the maximum possible value for pptr(). The space from
pptr() through epptr() is immediately available for
storing characters without a flush operation.
Non-virtual functions for setting pointers
These functions provide the only way to set the pointers.
Direct access is disallowed in order to ensure consistency
among the various pointers. The pointer arguments to a
function should all be zero to indicate that there is no
area (get, put, reserve). Using equal non-zero pointers
might result in improper behavior.
sbuf.setb(buf, end, del)
Establishes the reserve area (the buffer). Sets base()
to buf and ebuf() to end. If del is non-zero, the
buffer will be deleted whenever base() is changed by
another call to setb(), or when the streambuf destruc-
tor is invoked. If del is zero, the buffer will not be
deleted automatically by these functions.
sbuf.setg(back, g, eg)
Establishes the get area. Sets eback() to back, gptr()
to g, and egptr() to eg.
sbuf.setp(p, ep)
Establishes the put area. Sets pptr() to p and epptr()
to ep.
Other non-virtual functions
int i = sbuf.allocate()
This function is not called by any non-virtual member
of streambuf. It tries to set up a reserve area of an
unspecified default size. It returns zero and does
nothing if there is already a reserve area or if the
streambuf is marked unbuffered. Otherwise, it attempts
the allocation by calling the virtual function doallo-
cate(). It returns 1 on success, EOF on failure. See
below for unbuffered() and doallocate().
int i = sbuf.blen()
Returns the size in chars of the reserve area,
ebuf()-base().
sbuf.gbump(n)
Add n, a signed quantity, to the get pointer, without
any validity checks.
sbuf.pbump(n)
Add n, a signed quantity, to the put pointer, without
any validity checks.
int i = sbuf.unbuffered()
sbuf.unbuffered(i)
A streambuf has a private variable which keeps track of
whether the stream is buffered or unbuffered, indepen-
dent of whether a reserve area has been assigned. The
main use of this variable is to control whether allo-
cate() will actually allocate a reserve area. The
first form of the function returns nonzero if the vari-
able is set, zero otherwise. The second form sets the
variable if i is nonzero, clears it otherwise.
dpb()
Writes all the state variables of the streambuf as text
directly to file descriptor 1 (standard output). This
data is useful for debugging an implementation. It is
a public function so that it may be called anywhere for
debugging purposes, even though it is logically part of
the protected interface.
Virtual functions
These are the virtual functions which may be or should be
redefined by specialized buffer classes, as noted above.
Replacement functions should meet the specifications listed
here to ensure proper operation of other functions which may
depend on them. This section also documents the default
behavior of the base class versions of these functions.
int i = sbuf.doallocate()
This function is called by allocate when unbuffered()
is zero and base() is zero. It attempts to make a
buffer of suitable size available. On success it must
call setb to establish the reserve area, then return a
value greater than zero. On failure it returns EOF.
The default behavior is to allocate a buffer using new.
int i = sbuf.overflow(c)
This function is called to consume characters (flush
them to output), typically when the put area is full
and an attempt is made to store another character. If
c is not EOF, overflow must either store or consume the
character, following those already in the put area. It
returns EOF on error, any other value on success.
The default behavior of the base class version is unde-
fined, so each derived class must define its own over-
flow. The normal action for a derived class version is
to consume the characters in the put area (those
between pbase() and pptr()), call setp() to set up a
new put area, then store c (using sputc()) if it is not
EOF.
int i = sbuf.pbackfail(c)
This function is called when an attempt is made to put
back the character c and there is no space in the put-
back area; that is, eback()==gptr(). If this situation
can be handled, such as by repositioning an external
device, the derived class version of pbackfail should
do so and return c. If the character cannot be put
back for whatever reason, it should return EOF. The
default behavior of the base class version is to return
EOF.
streampos pos = sbuf.seekoff(off, dir, mode)
See sbufpub(3CC4) for a description of the parameters,
return value, and purpose of this function. The
abstract get and put pointers, as opposed to gptr() and
pptr() specifically, are modified by this function if
possible. A derived class version should return EOF if
the stream does not support repositioning or if there
is any error, and the new position otherwise. The
default behavior of the base class version is to return
EOF.
streampos pos2 = sbuf.seekpos(pos, mode)
See sbufpub(3CC4) for a description of the parameters,
return value, and purpose of this function. The
abstract get and put pointers, as opposed to gptr() and
pptr() specifically, are modified by this function if
possible. The default behavior of the base class ver-
sion is just to return the value of
sbuf.seekoff( (streamoff)pos, ios::beg, mode )
This means that it is usually only necessary to imple-
ment seekoff in a derived class, and inherit the base
class seekpos.
streambuf* sb = sbuf.setbuf(ptr, len)
A call of this function is a request to use the array
of len bytes starting at the location pointed to by ptr
as the buffer area. Setting ptr to zero or len to less
than or equal to zero requests an unbuffered state.
The derived class version may choose to ignore the
request. It should return the address of sbuf if it
accepts the request, EOF otherwise. The default
behavior of the base class version is to honor the
request if there is no reserve area.
int i = sbuf.sync()
This function synchronizes the streambuf with its
actual stream of characters. The derived class version
should flush any characters in the put area to their
final destination, and if possible give back any char-
acters in the input buffer to their source. It should
return EOF on any error, zero on success. The default
behavior of the base class version is to return zero if
there are no pending input or output characters
(in_avail() and out_waiting() are both zero), and
return EOF otherwise.
int i = sbuf.underflow()
This function is called to supply characters for input
(from some source) when the get area is empty, although
it may be called at other times. If the get area is
not empty, it should just return the first character
(without advancing the get pointer). If the get area
is empty, it should establish a new get area, aquire
new input, and return the first character, if any. If
no input characters are available, it should leave an
empty get area and return EOF. The default behavior of
the base class version is undefined, so each derived
class must define its own underflow.
SEE ALSO
ios.intro(3CC4), filebuf(3CC4), ios(3CC4), sbufpub(3CC4),
ssbuf(3CC4), stdiobuf(3CC4),
C++ Library Reference
Chapter 3, "The Classic iostream Library",
Environment."
Chapter 4, "Using Classic iostream in a Multithreaded