Your Browser is not longer supported

Please use Google Chrome, Mozilla Firefox or Microsoft Edge to view the page correctly
Loading...

{{viewport.spaceProperty.prod}}

sbufprot Protected interface of class streambuf


This section describes the protected and virtual parts of the streambuf class; especially interesting for derived classes.


#include <iostream.h>

typedef long streamoff, streampos;

class ios
{

public:
enum seek_dir {beg, cur, end};
enum open_mode {in, out, ate, app, trunc, nocreate, noreplace,

bin, tabexp};

// and lots of other stuff, see ios ...

} ;

class streambuf

{

public:


streambuf();
streambuf(char* p, int len);

virtual
void

˜streambuf();
dbp();

protected:

int
char*
int
char*
char*
char*
char*
void
char*
char*
void
char*
void
void
void
int
void
virtual int

allocate();
base();
blen() const;
eback();
ebuf();
egptr();
epptr();
gbump(int n);
gptr();
pbase();
pbump(int n);
pptr();
setb(char* b, char* eb, int a=0);
setg(char* eb, char* g, char* eg);
setp(char* p, char* ep);
unbuffered() const;
unbuffered(int);
doallocate();

public:

virtual int
virtual int

overflow(int c=EOF);
pbackfail(int c);

virtual streampos 


seekoff(streamoff, ios::seek_dir, int =ios::in|ios:out);

virtual streampos


seekpos(streampos, int =ios::in|ios:out);

virtual streambuf*


setbuf(char* p, int len);

virtual int
virtual int

sync();
underflow();

};



streambufs implement the buffer abstraction described in sbufpub. However, the streambuf class itself contains only basic members for manipulating the characters and normally a class derived from streambuf is used. This section describes the interface needed by programmers who are coding a derived class.

Broadly speaking there are two kinds of member functions described here. The non-virtual functions are provided for manipulating a streambuf in ways that are appropriate in a derived class. Their descriptions reveal details of the implementation that would be inappropriate in the public interface. The virtual functions permit the derived class to specialize the streambuf class in ways appropriate to the specific sources and sinks that it is implementing.

The descriptions of the virtual functions explain the obligations of the virtuals of the derived class. If the virtuals behave as specified, the streambuf behaves as specified inthe public interface. However, if the virtuals do not behave as specified, then the streambuf may not behave properly, and an iostream (or any other code) that relies onproper behaviour of the streambuf may not behave properly either.

In the following descriptions assume:

  • sb is a streambuf*.
  • ptr, b, eb, p, ep, g, and eg are char*
  • i, n, len and a are ints

  • c is an int character (positive or EOF).

  • pos is a streampos (see sbufpub).

  • off is a streamoff.

  • dir is a seek_dir.

  • mode is an int representing an open_mode.

Constructors

streambuf()

Constructs an empty buffer corresponding to an empty sequence.

streambuf(char * b, int len)

Constructs an empty buffer and then sets up the reserve area to be the len bytes starting at b.

The get, put, and reserve area

The protected members of streambuf present an interface to derived classes organizedaround three areas (arrays of bytes) managed cooperatively by the base and derivedclasses. They are the get area, the put area, and the reserve area (or buffer). The get and the put areas are normally disjointed, but they may both overlap the reserve area,whose primary purpose is to be a resource in which space for the put and get areascan be allocated. The get and the put areas are changed as characters are put into and taken from the buffer, but the reserve area normally remains fixed. The areas aredefined by a collection of char* values. The buffer abstraction is described in terms ofpointers that point between characters, but the char* values must point at chars. To establish a correspondence, the char* values should be thought of as pointing just before the byte they really point at.

Functions to examine the pointers

char * ptr=sb→base()

Returns a pointer to the first byte of the reserve area. Space between sb→base() and sb->ebuf() is the reserve area.

char * ptr=sb→eback()

Returns a pointer to a lower bound on sb->gptr(). Space between sb->eback() and sb->gptr() is available for putback.

char * ptr=sb→ebuf()

Returns a pointer to the byte after the last byte of the reserve area.

char * ptr=sb→egptr()

Returns a pointer to the byte after the last byte of the get area.

char * ptr=sb→epptr()

Returns a pointer to the byte after the last byte of the put area.

char * ptr=sb→gptr()

Returns a pointer to the first byte of the get area. The available characters are thosebetween sb->gptr() and sb->egptr(). The next character fetched is *(sb→gptr()) unless sb->egptr() is less than or equal to sb->gptr().

char * ptr=sb→pbase()

Returns a pointer to the put area base. Characters between sb->pbase() and sb->pptr() have been stored into the buffer and not yet consumed.

char * ptr=sb→pptr()

Returns a pointer to the first byte of the put area. The space between sb->pptr() andsb->epptr() is the put area and characters are stored here.

Functions for setting the pointers

Note

To indicate a particular area (get, put, or reserve) does not exist, all the associated pointers should be set to zero.

void sb->setb(char * b, char * eb, int i)

Sets base() and ebuf() to b and eb, respectively. i controls whether the area is subject to automatic deletion. If i is non-zero, then b is deleted when base is changed by another call of setb(), or when the destructor is called for *sb. If b and eb are both null then we say that there is no reserve area. If b is non-null, there is a reserve area even if eb is less than b, so the reserve area has zero length.

void sb->setp(char * p, char * ep)

Sets pptr() to p, pbase() to p, and epptr() to ep.

void sb->setg(char * eb, char * g, char * eg)

Sets eback() to eb, gptr() to g, and egptr() to eg.

Other non-virtual members

int i=sb→allocate()

Tries to set up a reserve area. If a reserve area already exists or if sb→unbuffered() is nonzero, allocate() returns 0 without doing anything. If the attempt to allocate space fails, allocate() returns EOF, otherwise (allocation succeeds) allocate() returns allocate() is not called by any non-virtual member function of streambuf.

int i=sb→blen()

Returns the size (in chars) of the current reserve area.

void dbp()

Writes directly on file descriptor 1 information in EBCDIC about the state of the buffer. It is intended for debugging and nothing is specified about the form of the output. It is considered part of the protected interface because the information it prints can only be understood in relation to that interface, but it is a public function so that it can be called anywhere during debugging.

void sb->gbump(int n)

Increments gptr() by n which may be positive or negative. No checks are made on whether the new value of gptr() is in bounds.

void sb->pbump(int n)

Increments pptr() by n which may be positive or negative. No checks are made on whether the new value of pptr() is in bounds.

void sb->unbuffered(int i)
int i=sb→unbuffered()

There is a private variable known as sb’s buffering state.
sb->unbuffered(i) sets the value of this variable to i and sb->unbuffered() returns the current value. This state is independent of the actual allocation of a reserve area.Its primary purpose is to determine whether a reserve area is allocated automaticallyby allocate.

Virtual member functions

Virtual functions may be redefined in derived classes to specialize the behaviour of streambufs. This section describes the behaviour that these virtual functions should have in any derived classes; the next section describes the behaviour that these functions are defined to have in base class streambuf.

int i=sb→doallocate()

Is called when allocate() determines that space is needed. doallocate() is required to call setb() to provide a reserve area or to return EOF if it cannot. It is only called if sb->unbuffered() is zero and sb->base() is zero.

int i=overflow(int c)

Is called to consume characters. If c is not EOF, overflow() also must either save or consume it. Usually it is called when the put area is full and an attempt is being made to store a new character, but it can be called at other times. The normal actionis to consume the characters between pbase() and pptr(), call setp() to establish a new put area, and if c!=EOF store it (using sputc()). sb->overflow() should return EOF to indicate an error; otherwise it should return something else.

int i=sb->pbackfail(int c)

Is called when eback() equals gptr() and an attempt has been made to putback c. If this situation can be dealt with (e.g., by repositioning an external file), pbackfail() should return c; otherwise it should return EOF.

streampos pos=sb->seekoff(streamoff off, seek_dir dir, int mode)

seekoff() is a public virtual member function. A detailed description is given in section sbufpub. Repositions the get and/or put pointers. Not all derived classes support repositioning.

streampos pos=sb->seekpos(streampos pos, int mode)

seekpos() is a public virtual member function. A detailed description is given in section sbufpub. Repositions the get and/or put pointers. Not all derived classes support repositioning.

streambuf * sb=sb->setbuf(char * ptr, int len)

Offers the array at ptr with len bytes to be used as a reserve area. The normal interpretation is that if ptr or len are zero then this is a request to make the sb unbuffered. The derived class may use this area or not as it chooses. If may acceptor ignore the request for unbuffered state as it chooses. setbuf() should return sb if it honours the request. Otherwise it should return 0.

int i=sb→sync()

sync() is a public virtual member function. A detailed description is given in section sbufpub.

int i=sb→underflow()

Is called to supply characters for fetching, i.e. to create a condition in which the get area is not empty. If it is called when there are characters in the get area it should return the first character. If the get area is empty, it should create a non-empty get area and return the next character (which it should also leave in the get area). If there are no more characters available, underflow() should return EOF and leave an empty get area.

The default definitions of the virtual functions

int i=sb→streambuf::doallocate()

Attempts to allocate a reserve area using operator new.

int i=sb->streambuf::overflow(int c)

streambuf::overflow() should be treated as if it had undefined behaviour. That is, derived classes should always define it.

int i=sb->streambuf::pbackfail(int c)

Returns EOF on failure and c on success.

streampos pos=sb->streambuf::seekpos(streampos pos, int mode)

Returns sb->seekoff(streamoff(pos),ios::beg,mode). Thus to define seeking in a derived class, it is frequently only necessary to define seekoff() and use the inherited streambuf::seekpos().

streampos pos=sb->streambuf::seekoff(streamoff off, seekdir dir, int mode)

Returns EOF.

streambuf * sb=sb->streambuf::setbuf(char* ptr, int len)

Honours the request when there is no reserve area.

int i=sb→streambuf::sync()

Returns 0 if the get area is empty and there are no unconsumed characters.
Otherwise it returns EOF.

int i=sb→streambuf::underflow()

streambuf::underflow() should be treated as if it had undefined behaviour. That is, it should always be defined in derived classes.

EXAMPLE

The program prints the address of the base area of a class derived from a streambuf.

The program is an example of displaying memory contents. It could have other trivial member functions like get_base which return the addresses of the get and put areas..

#include <iostream.h>
const int N = 20;
class trivial : public streambuf
{
  int a;                /* Some sample data in a class       */
  public:
  trivial() : streambuf(new char[ N], N)
  {
    /* Define trivial constructor by streambuf constructor   */
    a = 0;
  };
   ̃trivial() {};
  /* Assume streambuf destructor will delete the N byte      */
  /* reserve area                                            */
  char * get_base()
  {
    /* We need this function because the streambuf::base()   */
    /* member function is protected.                         */
    /* We don't need the streambuf:: qualifier since scope   */
    /* is ok.                                                */
    return base();
  };
};
int main()
{
  trivial test_var;
  cout << (void *) test_var.get_base() << endl;
  /* We must cast to void * to stop cout displaying the     */
  /* contents of the first byte of the reserve area.        */
  return 0;
}

The result of executing the program is:

0xc6008
%  CCM0998 CPU time used: 0.0005 seconds

Note that the value stored in the pointer may vary, and that cout has a default format for pointer values..

BUGS

The constructors are public for compatibility with the old stream package. They ought to be protected.

The interface for unbuffered actions is awkward. It’s hard to write underflow() and overflow() virtuals that behave properly for unbuffered streambuf()s without special casing. Also there is no way for the virtuals to react sensibly to multi-character gets or puts.

Although the public interface to streambufs deals in characters and bytes, the interface to derived classes deals in chars. Since a decision had to be made on the types of the real data pointers, it seemed easier to reflect that choice in the types of the protected members than to duplicate all the members with both plain char and unsigned char versions. But perhaps all these uses of char* ought to have been with a typedef.

SEE ALSO


istream, sbufpub