Several complexities might be encountered when overriding tt(underflow)
especially when buffers must repeatedly be refreshed and loaded. They are:
    itemization(
    it() How to keep track of the over-all current offset?
    it() The actions performed by tt(underflow) and tt(overflow).
    it() Should tt(uflow) be overridden?
    it() Which members are called by which stream read/write requests?
    it() Overriding tt(xsgetn).
    it() Overriding tt(xsputn).
    )

    figure(polymorphism/buffers)
        (Multi-buffer I/O handling)
        (BuffersFig)

Figure ref(BuffersFig) shows a situation where multiple buffers are used: the
device's information is made available in a buffer which is processed and
managed by the derived tt(streambuf) class. In this figure the following
variables are introduced:
    itemization(
    itt(offset) is the device's current position. Its lower limit is 0,
        and for all practical purposes there is no upper limit.
    itt(maxEnd), however, is the device's current physical maximum offset
        value. Such a physical maximum may not exist, but it em(does) exist if,
        e.g., a physical buffer in memory is used which cannot contain more
        than a fixed number of bytes. In those cases tt(maxEnd) is set to that
        maximum value, representing the offset just beyond the highest offset
        where a byte may be written to the device;
    itt(getEnd) is the current maximum number of characters that can be read
        from the device. With a newly defined device its value is 0 (zero),
        but once bytes are written to the device tt(getEnd) is updated to the
        position just beyond to the highest ever offset where a byte was
        written. When disk-files are used tt(getEnd) would be equal to the
        file's size;
    it() All of the device's information cannot at once be made available in
        the tt(streambuf's) buffer. Instead it is split up in blocks of a
        fixed size. The device's offset of the first byte of such a
        block is available in tt(bufBeg), and the offset just beyond the last
        byte of such a block is available in tt(bufEnd); tt(bufEnd) never
        exceeds tt(maxEnd).
    )

This section covers how such multi-buffer data can be handled by tt(iostream)
objects: streams supporting reading em(and) writing. Such streams offer
tt(seekg) and tt(seekp) members, but the device's offset position applies to
both tt(seekg) and tt(seekp): after either tt(seekg) or tt(seekp) reading and
writing both start at the position defined by either of these two seek
members. Furthermore, when switching between reading and writing no
tt(seekg/seekp) call is required: by default new read or write requests
continue at the device's current offset, set by the last read, write, or seek
request.

