SBUFPROT(3C++)

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(3C++) 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(3C++). 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(3C++), ssbuf(3C++), stdiobuf(3C++).

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 functionality, and their default behavior. Where the default behavior is suitable for a derived buffer class, the function 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 continue 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 implement 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 contains the characters immediately available for input. The put area holds characters stored for output but not yet consumed 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(3C++),

  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 unbuffered.

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 characters 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 destructor 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 doallocate(). 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, independent of whether a reserve area has been assigned. The main use of this variable is to control whether allocate() will actually allocate a reserve area. The first form of the function returns nonzero if the variable 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 undefined, so each derived class must define its own overflow. 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 putback 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(3C++) 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(3C++) 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 version is just to return the value of
    sbuf.seekoff( (streamoff)pos, ios::beg, mode )
    This means that it is usually only necessary to implement 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 characters 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(3C++), filebuf(3C++), ios(3C++), sbufpub(3C++), ssbuf(3C++), stdiobuf(3C++),

C++ 4.1 Library Reference Manual:

Chapter 4, "The Iostream Library",

Chapter 5, "Using libC in a Multithreaded Environment."