1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
|
The em(protected) members of the class tt(streambuf) are important for
understanding and using tt(streambuf) objects. Athough there are both
protected i(data members) and protected i(member functions) defined in the
tt(class streambuf) the protected em(data) members are not mentioned here as
using them would violates the principle of emi(data hiding). As
tt(streambuf)'s set of member functions is quire extensive directly using its
data members is probably hardly ever necessary. This section not even lists
all protected member functions but lists only those that are useful for
constructing specializations.
tt(Streambuf) objects control a buffer, used for input and/or output, for
which begin-, actual- and end-pointers have been defined, as depicted in
figure ref(SBBUFFERS).
figure(iostreams/sbbuffers)
(Input- and output buffer pointers of the class `streambuf')
(SBBUFFERS)
tt(Streambuf) offers one protected constructor:
itemization(
ittq(streambuf::streambuf())
(Default (protected) constructor of the tt(class streambuf).)
)
Several protected member functions are available for input operations. The
member functions marked tt(virtual) may or course be redefined in derived
classes:
itemization(
ithtq(eback)
(char *eback())
(tt(Streambuf) maintains three pointers controlling its input buffer:
tt(eback) points to the `end of the putback' area: characters can
safely be put back up to this position. See also figure
ref(SBBUFFERS). tt(Eback) points to the em(beginning) of the input
buffer.)
ithtq(egptr)
(char *egptr())
(tt(Egptr) points just beyond the last character that can be retrieved
from the input buffer. See also figure ref(SBBUFFERS). If tt(gptr)
equals tt(egptr) the buffer must be refilled. This should be
implemented by calling tt(underflow), see below.)
ithtq(gbump)
(void gbump(int n))
(The object's tt(gptr) (see below) is advanced over tt(n) positions.)
ithtq(gptr) (char *gptr()) (tt(Gptr) points to the next character to be
retrieved from the object's input buffer. See also figure
ref(SBBUFFERS).)
ithtq(pbackfail)
(virtual int pbackfail(int c))
(This member function may be overridden by derived classes to do
something intelligent when putting back character tt(c) fails. One
might consider restoring the old read pointer when input buffer's
begin has been reached. This member function is called when ungetting
or putting back a character fails. In particular, it is called when
itemization(
itt(gptr() == 0): no buffering used,
itt(gptr() == eback()): no more room to push back,
itt(*gptr() != c): a different character than the next character
to be read must be pushed back.
)
If tt(c == endOfFile()) then the input device must be reset by one
character position. Otherwise tt(c) must be prepended to the
characters to be read. The function should return endOfFile() on
failure. Otherwise 0 can be returned.)
ithtq(setg)
(void setg(char *beg, char *next, char *beyond))
(This member function initializes an input buffer. tt(beg) points to
the beginning of the input area, tt(next) points to the next character
to be retrieved, and tt(beyond) points to the location just beyond the
input buffer's last character. Ususally tt(next) is at least tt(beg +
1), to allow for a put back operation. No input buffering is used when
this member is called as tt(setg(0, 0, 0)). See also the member
tt(uflow), below.)
ithtq(showmanyc)
(virtual streamsize showmanyc())
((Pronounce: s-how-many-c) This member function may be overridden by
derived classes. It must return a guaranteed lower bound on the number
of characters that can be read from the device before tt(uflow) or
tt(underflow) returns endOfFile(). By default 0 is returned (meaning
no or some characters will be returned before the latter two functions
return endOfFile()). When a positive value is returned then the next
call of tt(u(nder)flow) will not return endOfFile().)
ithtq(uflow)
(virtual int uflow())
(This member function may be overridden by derived classes to reload an
input buffer with fresh characters. Its default implementation is to
call tt(underflow) (see below). If tt(underflow()) fails, endOfFile()
is returned. Otherwise, the next character available character is
returned as tt(*gptr()) following a tt(gbump(-1)). tt(Uflow) also
moves the pending character that is returned to the backup
sequence. This is different from tt(underflow()), which merely returns
the next available character, but does not alter the input pointer
positions.
When em(no) input buffering is required this function,
rather than tt(underflow), can be overridden to produce the next
available character from the device to read from.)
ithtq(underflow)
(virtual int underflow())
(This member function may be overridden by derived classes to read
another character from the device. The default implementation is to
return endOfFile().
It is called when
itemization(
it() there is no input buffer (tt(eback() == 0))
itt(gptr() >= egptr()): the input buffer is exhausted.
)
Often, when buffering is used, the complete buffer
is not refreshed as this would make it impossible to put back
characters immediately following a reload. Instead, buffers are often
refreshed in halves. This system is called a emi(split buffer).
Classes derived from tt(streambuf) for reading normally at least
override tt(underflow). The prototypical example of an overridden
tt(underflow) function looks like this:
verb(
int underflow()
{
if (not refillTheBuffer()) // assume a member d_buffer is available
return EOF;
// reset the input buffer pointers
setg(d_buffer, d_buffer, d_buffer + d_nCharsRead);
// return the next available character
// (the cast is used to prevent
// misinterpretations of 0xff characters
// as EOF)
return static_cast<unsigned char>(*gptr());
}
)
)
ithtq(xsgetn)
(virtual streamsize xsgetn(char *buffer, streamsize n))
(This member function may be overridden by derived classes to retrieve
at once tt(n) characters from the input device. The default
implementation is to call tt(sbumpc) for every single character
meaning that by default this member (eventually) calls tt(underflow)
for every single character. The function returns the actual number of
characters read or enfOfFile(). If endOfFile() is returned the
tt(streambuf) will stop reading the device.)
)
The following protected members are available for output
operations. Again, some members may be overridden by derived classes:
itemization(
ithtq(overflow)
(virtual int overflow(int c))
(This member function may be overridden by derived classes to flush the
characters currently stored in the output buffer to the output device,
and then to reset the output buffer pointers so as to represent an
empty buffer. Its parameter tt(c) is initialized to the next character
to be processed. If no output buffering is used tt(overflow) is called
for every single character that is written to the tt(streambuf)
object. No output buffering is accomplised by setting the buffer
pointers (using, tt(setp), see below) to 0. The
i(default implementation) returns endOfFile(), indicating that no
characters can be written to the device.
Classes derived from tt(streambuf) for writing normally at least
override tt(overflow). The prototypical example of an overridden
tt(overflow) function looks like this:
verb(
int OFdStreambuf::overflow(int c)
{
sync(); // flush the buffer
if (c != EOF) // write a character?
{
*pptr() = static_cast<char>(c); // put it into the buffer
pbump(1); // advance the buffer's pointer
}
return c;
}
)
)
ithtq(pbase)
(char *pbase())
(tt(Streambuf) maintains three pointers controlling its output buffer:
tt(pbase) points to the beginning of the output buffer area. See also
figure ref(SBBUFFERS).)
ithtq(pptr)
(char *epptr())
(tt(Streambuf) maintains three pointers controlling its output buffer:
tt(epptr) points just beyond the output buffer's last available
location. See also figure ref(SBBUFFERS). If tt(pptr) (see below)
equals tt(epptr) the buffer must be flushed. This is implemented by
calling tt(overflow), see before.)
ithtq(pbump)
(void pbump(int n))
(The location returned by tt(pptr) (see below) is advanced by
tt(n). The next character to write will be entered at that location.)
ithtq(pptr)
(char *pptr())
(tt(Streambuf) maintains three pointers controlling its output buffer:
tt(pptr) points to the location in the output buffer where the next
available character should be written. See also figure
ref(SBBUFFERS).)
ithtq(setp)
(void setp(char *beg, char *beyond))
(tt(Streambuf)'s output buffer is initialized to the locations passed
to tt(setp). tt(Beg) points to the beginning of the output buffer and
tt(beyond) points just beyond the last available location of the
output buffer. Use tt(setp(0, 0) to indicate that i(no buffering)
should be used. In that case tt(overflow) is called for every single
character to write to the device.)
ithtq(xsputn)
(streamsize xsputn(char const *buffer, streamsize n))
(This member function may be overridden by derived classes to write a
series of at most tt(n) characters to the output buffer. The actual
number of inserted characters is returned. If endOfFile() is returned
writing to the device stops. The default implementation
calls tt(sputc) for each individual character, so redefining this
member is only necessary if a more efficient implementation is
required.)
)
Several protected members are related to buffer management and positioning:
itemization(
ithtq(setbuf)
(virtual streambuf *setbuf(char *buffer, streamsize n))
(This member function may be overridden by derived classes to install a
buffer. The default implementation is to do nothing. It is called by
tt(pubsetbuf).)
it()hi(seekoff)
tt(virtual
pos_type seekoff+OPENPARoff_type offset, ios::seekdir way,)nl()
tt(ios::openmode mode = ios::in | ios::out+CLOSEPAR)
quote(This member function may be overridden by derived classes to
reset the next pointer for input or output to a new relative
position (using
hi(cur)hi(beg)tt(ios::beg, ios::cur) or hi(end)tt(ios::end)). The
default implementation indicates failure by returning -1. The function
is called when tt(tellg) or tt(tellp) are called. When derived class
supports seeking, then it should also define this function to handle
repositioning requests. It is called by ti(pubseekoff). The
new position or an invalid position (i.e., -1) is returned.)
it() hi(seekpos)
tt(virtual pos_type seekpos+OPENPARpos_type offset,
ios::openmode mode =)nl()
tt(ios::in | ios::out+CLOSEPAR):
quote(This member function may be overridden by derived classes to
reset the next pointer for input or output to a new absolute
position (i.e, relative to tt(ios::beg)). The default implementation
indicates failure by returning -1.)
ithtq(sync)
(virtual int sync())
(This member function may be overridden by derived classes to flush the
output buffer to the output device or to reset the input device just
betond the position of the character that was returned last. It
returns 0 on success, -1 on failure. The default implementation (not
using a buffer) is to return 0, indicating successful syncing. This
member is used to ensure that any characters that are still buffered
are written to the device or to put unconsumed characters back to the
device when the tt(streambuf) object ceases to exist.)
)
)
When classes are derived from tt(streambuf) at least tt(underflow) should
be overridden by classes intending to read information from devices, and
tt(overflow) should be overridden by classes intending to write information to
devices. Several examples of classes derived from tt(streambuf) are provided
in chapter ref(CONCRETE).
tt(Fstream) class type objects use a combined input/output buffer. This is
a result from that tt(istream) and tt(ostream) being virtually derived from
tt(ios), which class contains the tt(streambuf). To construct a class
supporting both input and output using separate buffers, the tt(streambuf)
itself may define two buffers. When tt(seekoff) is called for reading, a
tt(mode) parameter can be set to tt(ios::in), otherwise to tt(ios::out). Thus
the derived class knows whether it should access the tt(read) buffer or the
tt(write) buffer. Of course, tt(underflow) and tt(overflow) do not have to
inspect the mode flag as they by implication know on which buffer they should
operate.
|