Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component bdlsb_overflowmemoutstreambuf
[Package bdlsb]

Provide an overflowable output streambuf using a client buffer. More...

Namespaces

namespace  bdlsb

Detailed Description

Outline
Purpose:
Provide an overflowable output streambuf using a client buffer.
Classes:
bdlsb::OverflowMemOutStreamBuf overflowable output bsl::streambuf
See also:
Component bdlsb_overflowmemoutput
Description:
This component implements the output portion of the bsl::basic_streambuf protocol using a user-supplied initial buffer and a dynamically allocated overflow buffer. As with bdlsb_fixedmemoutput, users supply the character buffer at construction. Unlike bdlsb_fixedmemoutput, they can no longer reinitialize the stream buffer with a different character buffer by calling the pubsetbuf method; instead, if that buffer runs out, the bdlsb::OverflowMemOutStreamBuf will allocate another buffer (see "Overflow Buffer" below). The only difference between this component and bdlsb_overflowmemoutput is that the class bdlsb::OverflowMemOutStreamBuf is derived from a bsl::streambuf. Method names necessarily correspond to those specified by the protocol. Refer to the C++ Standard, Section 27.5.2, for a full specification of the bsl::basic_streambuf interface. This component provides none of the input-related functionality of basic_streambuf (see Streaming Architecture, below), nor does it use locales in any way.
Overflow Buffer:
This output stream buffer will use the initial buffer (supplied at construction) as its output buffer. If an overflow of the initial buffer were to occur, an additional buffer (the overflow buffer) will be allocated. If this overflow buffer ever becomes full, it will be automatically grown. The overflow buffer grows geometrically (to twice the current overflow buffer size) whenever the amount of data written exceeds the amount of space available. On growth, the old overflow buffer is copied over to the newly allocated overflow buffer, and then deallocated, thus after any write/seek forward one cannot assume that the overflow buffer is still the same memory. Data in the overflow buffer beyond the reach of the current write position is not guaranteed to be preserved after a growth operation.
Streaming Architecture:
Stream buffers are designed to decouple device handling from content formatting, providing the requisite device handling and possible buffering services, and leaving the formatting to the client stream. The standard C++ IOStreams library further partitions streaming into input streaming and output streaming, separating responsibilities for each at both the stream layer and the stream buffer layer. The BDE streaming library for bdex, including all of bdlsb, follows this model.
Usage:
This section illustrates intended use of this component.
Example 1: Basic Use of bdlsb::OverflowMemOutStreamBuf:
This example demonstrates using a bdlsb::OverflowMemOutStreamBuf in order to test a user defined stream type, CapitalizingStream. In this example, we'll define a simple example stream type CapitalizingStream that capitalizes lower-case ASCII data written to the stream. In order to test this CapitalizingStream type, we'll create an instance, and supply it a bdlsb::OverflowMemOutStreamBuf object as its stream buffer; after we write some character data to the CapitalizingStream we'll inspect the buffer of the bdlsb::OverflowMemOutStreamBuf and verify its contents match our expected output. Note that to simplify the example, we do not include the functions for streaming non-character data, e.g., numeric values.
First, we define our example stream class, CapitalizingStream (which we will later test using 'bdlsbOverflowMemOutStreamBuf):
  class CapitalizingStream {
      // This class capitalizes lower-case ASCII characters that are output.

      // DATA
      bsl::streambuf  *d_streamBuffer_p;   // pointer to a stream buffer

      // FRIENDS
      friend CapitalizingStream& operator<<(CapitalizingStream&  stream,
                                            const char          *data);
    public:
      // CREATORS
      explicit CapitalizingStream(bsl::streambuf *streamBuffer);
          // Create a capitalizing stream using the specified 'streamBuffer'
          // as the underlying stream buffer for the stream.
  };

  // FREE OPERATORS
  CapitalizingStream& operator<<(CapitalizingStream&  stream,
                                 const char          *data);
      // Write the specified 'data' in capitalized form to the specified
      // 'stream'.

  CapitalizingStream::CapitalizingStream(bsl::streambuf *streamBuffer)
  : d_streamBuffer_p(streamBuffer)
  {
  }
As is typical, the streaming operators are made friends of the class.
Note that we cannot directly use bsl::toupper to capitalize each individual character, because bsl::toupper operates on int instead of char. Instead, we call a function ucharToUpper that works in terms of unsigned char. some care must be made to avoid undefined and implementation-specific behavior during the conversions to and from int. Therefore we wrap bsl::toupper in an interface that works in terms of unsigned char:
  static unsigned char ucharToUpper(unsigned char input)
      // Return the upper-case equivalent to the specified 'input' character.
  {
      return static_cast<unsigned char>(bsl::toupper(input));
  }
Finally, we use the transform algorithm to convert lower-case characters to upper-case.
  // FREE OPERATORS
  CapitalizingStream& operator<<(CapitalizingStream&  stream,
                                 const char          *data)
  {
      bsl::string tmp(data);
      bsl::transform(tmp.begin(),
                     tmp.end(),
                     tmp.begin(),
                     ucharToUpper);
      stream.d_streamBuffer_p->sputn(tmp.data(), tmp.length());
      return stream;
  }
Now, we create an instance of bdlsb::OverflowMemOutStreamBuf that will serve as underlying stream buffer for our CapitalingStream:
  enum { INITIAL_CAPACITY = 10 };
  char buffer[INITIAL_CAPACITY];

  bdlsb::OverflowMemOutStreamBuf streamBuffer(buffer, INITIAL_CAPACITY);
Now, we test our CapitalingStream by supplying the created instance of bdlsb::OverflowMemOutStreamBuf and using it to inspect the output of the stream:
  CapitalizingStream  testStream(&streamBuffer);
  testStream << "Hello world.";
Finally, we verify that the streamed data has been capitalized and the portion of the data that does not fit into initial buffer is placed into dynamically allocated overflow buffer:
  assert(10 == streamBuffer.dataLengthInInitialBuffer());
  assert(0  == strncmp("HELLO WORL",
                       streamBuffer.initialBuffer(),
                       streamBuffer.dataLengthInInitialBuffer()));
  assert(2  == streamBuffer.dataLengthInOverflowBuffer());
  assert(0  == strncmp("D.",
                       streamBuffer.overflowBuffer(),
                       streamBuffer.dataLengthInOverflowBuffer()));