BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlsb_overflowmemoutstreambuf.h
Go to the documentation of this file.
1/// @file bdlsb_overflowmemoutstreambuf.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlsb_overflowmemoutstreambuf.h -*-C++-*-
8#ifndef INCLUDED_BDLSB_OVERFLOWMEMOUTSTREAMBUF
9#define INCLUDED_BDLSB_OVERFLOWMEMOUTSTREAMBUF
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlsb_overflowmemoutstreambuf bdlsb_overflowmemoutstreambuf
15/// @brief Provide an overflowable output `streambuf` using a client buffer.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlsb
19/// @{
20/// @addtogroup bdlsb_overflowmemoutstreambuf
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlsb_overflowmemoutstreambuf-purpose"> Purpose</a>
25/// * <a href="#bdlsb_overflowmemoutstreambuf-classes"> Classes </a>
26/// * <a href="#bdlsb_overflowmemoutstreambuf-description"> Description </a>
27/// * <a href="#bdlsb_overflowmemoutstreambuf-overflow-buffer"> Overflow Buffer </a>
28/// * <a href="#bdlsb_overflowmemoutstreambuf-streaming-architecture"> Streaming Architecture </a>
29/// * <a href="#bdlsb_overflowmemoutstreambuf-usage"> Usage </a>
30/// * <a href="#bdlsb_overflowmemoutstreambuf-example-1-basic-use-of-bdlsb-overflowmemoutstreambuf"> Example 1: Basic Use of bdlsb::OverflowMemOutStreamBuf </a>
31///
32/// # Purpose {#bdlsb_overflowmemoutstreambuf-purpose}
33/// Provide an overflowable output `streambuf` using a client buffer.
34///
35/// # Classes {#bdlsb_overflowmemoutstreambuf-classes}
36///
37/// - bdlsb::OverflowMemOutStreamBuf: overflowable output `bsl::streambuf`
38///
39/// @see bdlsb_overflowmemoutput
40///
41/// # Description {#bdlsb_overflowmemoutstreambuf-description}
42/// This component implements the output portion of the
43/// `bsl::basic_streambuf` protocol using a user-supplied initial buffer and a
44/// dynamically allocated overflow buffer. As with @ref bdlsb_fixedmemoutput ,
45/// users supply the character buffer at construction. Unlike
46/// @ref bdlsb_fixedmemoutput , they can no longer reinitialize the stream buffer
47/// with a different character buffer by calling the `pubsetbuf` method;
48/// instead, if that buffer runs out, the `bdlsb::OverflowMemOutStreamBuf` will
49/// allocate another buffer (see "Overflow Buffer" below). The only difference
50/// between this component and @ref bdlsb_overflowmemoutput is that the class
51/// `bdlsb::OverflowMemOutStreamBuf` is derived from a `bsl::streambuf`. Method
52/// names necessarily correspond to those specified by the protocol. Refer to
53/// the C++ Standard, Section 27.5.2, for a full specification of the
54/// `bsl::basic_streambuf` interface. This component provides none of the
55/// input-related functionality of @ref basic_streambuf (see Streaming
56/// Architecture, below), nor does it use locales in any way.
57///
58/// ## Overflow Buffer {#bdlsb_overflowmemoutstreambuf-overflow-buffer}
59///
60///
61/// This output stream buffer will use the initial buffer (supplied at
62/// construction) as its output buffer. If an overflow of the initial buffer
63/// were to occur, an additional buffer (the overflow buffer) will be allocated.
64/// If this overflow buffer ever becomes full, it will be automatically grown.
65/// The overflow buffer grows geometrically (to twice the current overflow
66/// buffer size) whenever the amount of data written exceeds the amount of space
67/// available. On growth, the old overflow buffer is copied over to the newly
68/// allocated overflow buffer, and then deallocated, thus after any write/seek
69/// forward one cannot assume that the overflow buffer is still the same memory.
70/// Data in the overflow buffer beyond the reach of the current write position
71/// is not guaranteed to be preserved after a growth operation.
72///
73/// ## Streaming Architecture {#bdlsb_overflowmemoutstreambuf-streaming-architecture}
74///
75///
76/// Stream buffers are designed to decouple device handling from content
77/// formatting, providing the requisite device handling and possible buffering
78/// services, and leaving the formatting to the client stream. The standard
79/// C++ IOStreams library further partitions streaming into input streaming and
80/// output streaming, separating responsibilities for each at both the stream
81/// layer and the stream buffer layer. The BDE streaming library for `bslx`,
82/// including all of `bdlsb`, follows this model.
83///
84/// ## Usage {#bdlsb_overflowmemoutstreambuf-usage}
85///
86///
87/// This section illustrates intended use of this component.
88///
89/// ### Example 1: Basic Use of bdlsb::OverflowMemOutStreamBuf {#bdlsb_overflowmemoutstreambuf-example-1-basic-use-of-bdlsb-overflowmemoutstreambuf}
90///
91///
92/// This example demonstrates using a `bdlsb::OverflowMemOutStreamBuf` in order
93/// to test a user defined stream type, `CapitalizingStream`. In this example,
94/// we'll define a simple example stream type `CapitalizingStream` that
95/// capitalizes lower-case ASCII data written to the stream. In order to test
96/// this `CapitalizingStream` type, we'll create an instance, and supply it a
97/// `bdlsb::OverflowMemOutStreamBuf` object as its stream buffer; after we write
98/// some character data to the `CapitalizingStream` we'll inspect the buffer of
99/// the `bdlsb::OverflowMemOutStreamBuf` and verify its contents match our
100/// expected output. Note that to simplify the example, we do not include the
101/// functions for streaming non-character data, e.g., numeric values.
102///
103/// First, we define our example stream class, `CapitalizingStream` (which we
104/// will later test using 'bdlsb::OverflowMemOutStreamBuf):
105/// @code
106/// /// This class capitalizes lower-case ASCII characters that are output.
107/// class CapitalizingStream {
108///
109/// // DATA
110/// bsl::streambuf *d_streamBuffer_p; // pointer to a stream buffer
111///
112/// // FRIENDS
113/// friend CapitalizingStream& operator<<(CapitalizingStream& stream,
114/// const char *data);
115/// public:
116/// // CREATORS
117///
118/// /// Create a capitalizing stream using the specified `streamBuffer` as
119/// /// the underlying stream buffer for the stream.
120/// explicit CapitalizingStream(bsl::streambuf *streamBuffer);
121/// };
122///
123/// // FREE OPERATORS
124///
125/// /// Write the specified `data` in capitalized form to the specified
126/// /// `stream`.
127/// CapitalizingStream& operator<<(CapitalizingStream& stream,
128/// const char *data);
129///
130/// CapitalizingStream::CapitalizingStream(bsl::streambuf *streamBuffer)
131/// : d_streamBuffer_p(streamBuffer)
132/// {
133/// }
134/// @endcode
135/// As is typical, the streaming operators are made friends of the class.
136///
137/// Note that we cannot directly use `bsl::toupper` to capitalize each
138/// individual character, because `bsl::toupper` operates on `int` instead of
139/// `char`. Instead, we call a function `ucharToUpper` that works in terms of
140/// `unsigned char`. some care must be made to avoid undefined and
141/// implementation-specific behavior during the conversions to and from `int`.
142/// Therefore we wrap `bsl::toupper` in an interface that works in terms of
143/// `unsigned char`:
144/// @code
145/// /// Return the upper-case equivalent to the specified `input` character.
146/// static unsigned char ucharToUpper(unsigned char input)
147/// {
148/// return static_cast<unsigned char>(bsl::toupper(input));
149/// }
150/// @endcode
151/// Finally, we use the `transform` algorithm to convert lower-case characters
152/// to upper-case.
153/// @code
154/// // FREE OPERATORS
155/// CapitalizingStream& operator<<(CapitalizingStream& stream,
156/// const char *data)
157/// {
158/// bsl::string tmp(data);
159/// bsl::transform(tmp.begin(),
160/// tmp.end(),
161/// tmp.begin(),
162/// ucharToUpper);
163/// stream.d_streamBuffer_p->sputn(tmp.data(), tmp.length());
164/// return stream;
165/// }
166/// @endcode
167/// Now, we create an instance of `bdlsb::OverflowMemOutStreamBuf` that will
168/// serve as underlying stream buffer for our `CapitalingStream`:
169/// @code
170/// enum { INITIAL_CAPACITY = 10 };
171/// char buffer[INITIAL_CAPACITY];
172///
173/// bdlsb::OverflowMemOutStreamBuf streamBuffer(buffer, INITIAL_CAPACITY);
174/// @endcode
175/// Now, we test our `CapitalingStream` by supplying the created instance of
176/// `bdlsb::OverflowMemOutStreamBuf` and using it to inspect the output of the
177/// stream:
178/// @code
179/// CapitalizingStream testStream(&streamBuffer);
180/// testStream << "Hello world.";
181/// @endcode
182/// Finally, we verify that the streamed data has been capitalized and the
183/// portion of the data that does not fit into initial buffer is placed into
184/// dynamically allocated overflow buffer:
185/// @code
186/// assert(10 == streamBuffer.dataLengthInInitialBuffer());
187/// assert(0 == strncmp("HELLO WORL",
188/// streamBuffer.initialBuffer(),
189/// streamBuffer.dataLengthInInitialBuffer()));
190/// assert(2 == streamBuffer.dataLengthInOverflowBuffer());
191/// assert(0 == strncmp("D.",
192/// streamBuffer.overflowBuffer(),
193/// streamBuffer.dataLengthInOverflowBuffer()));
194/// @endcode
195/// @}
196/** @} */
197/** @} */
198
199/** @addtogroup bdl
200 * @{
201 */
202/** @addtogroup bdlsb
203 * @{
204 */
205/** @addtogroup bdlsb_overflowmemoutstreambuf
206 * @{
207 */
208
209#include <bdlscm_version.h>
210
211#include <bslma_allocator.h>
212#include <bslma_default.h>
214
216
217#include <bsls_keyword.h>
218
219#include <bsl_cstddef.h>
220#include <bsl_ios.h>
221#include <bsl_streambuf.h>
222
223
224namespace bdlsb {
225
226 // =============================
227 // class OverflowMemOutStreamBuf
228 // =============================
229
230/// This class implements the output functionality of the
231/// `bsl::basic_streambuf` protocol, using client-supplied memory and
232/// client-supplied allocator if additional memory is needed.
233///
234/// See @ref bdlsb_overflowmemoutstreambuf
235class OverflowMemOutStreamBuf : public bsl::streambuf {
236
237 // DATA
238 // The order of the data members is determined by our usage pattern for
239 // cache efficiency. Do not reorder them.
240 //
241 // 'd_dataLength' is marked 'mutable' because it is used to cache the
242 // length of the data written to the stream buffer. Characters can be
243 // written to the buffer via the base class (without calling a manipulator
244 // on this class), so this cached value is updated when accessors are
245 // called.
246
247 mutable bsl::size_t d_dataLength; // total data length
248
249 char *d_initialBuffer_p; // user-supplied buffer
250 // (held, not owned)
251
252 bsl::size_t d_initialBufferSize; // size of initial buffer
253
254 bool d_inOverflowBufferFlag; // true if 'pptr' points into
255 // the overflow buffer
256
257 char *d_overflowBuffer_p; // overflow buffer (owned)
258
259 bsl::size_t d_overflowBufferSize; // size of overflow buffer
260
261 bslma::Allocator *d_allocator_p; // memory allocator (held,
262 // not owned)
263
264 // NOT IMPLEMENTED
267
268 private:
269 // PRIVATE MANIPULATORS
270
271 /// Replace the overflow buffer with another buffer larger by at least
272 /// the specified `numBytes`, by growing geometrically by a factor of
273 /// two, and preserve the bytes that are in use by the overflow buffer,
274 /// as determined by the `d_dataLength`. Note that `pptr()` is not
275 /// updated at this time, and may be pointing to deallocated memory when
276 /// this returns. Also note, that because `d_dataLength` is used to
277 /// determine the amount of data in the buffer, this function should be
278 /// called after `privateSync`.
279 void grow(bsl::size_t numBytes);
280
281 /// Set `d_dataLength` to the amount of data that has been written to
282 /// this stream buffer, from the beginning of the stream to the current
283 /// `pptr()` position. Note that if `pptr()` points into the overflow
284 /// buffer, this size the initial buffer, plus the portion of the
285 /// overflow buffer that has been written to.
286 void privateSync() const;
287
288 protected:
289 // PROTECTED VIRTUAL FUNCTIONS
290
291 // *** 27.5.2.4.2 buffer management and positioning ***
292
293 /// Set the position indicator to the relative specified `offset` from the
294 /// base position indicated by the specified `way` and return the resulting
295 /// absolute position on success or pos_type(-1) on failure. Optionally
296 /// specify `which` area of the stream buffer. The seek operation will
297 /// fail if `which` does not include the flag `bsl::ios_base::out` or if
298 /// the resulting absolute position is negative.
299 pos_type seekoff(
300 off_type offset,
301 bsl::ios_base::seekdir way,
302 bsl::ios_base::openmode which = bsl::ios_base::in | bsl::ios_base::out)
304
305 /// Set the position indicator to the specified `position` and return the
306 /// resulting absolute position on success or pos_type(-1) on failure.
307 /// Optionally specify `which` area of the stream buffer. The `seekpos`
308 /// operation will fail if `which` does not include the flag
309 /// `bsl::ios_base::out` or if `position` is negative.
310 pos_type seekpos(
311 pos_type position,
312 bsl::ios_base::openmode which = bsl::ios_base::in | bsl::ios_base::out)
314
315 /// Set `d_dataLength` to the amount of data that has been written to this
316 /// stream buffer, from the beginning of the stream to the current `pptr()`
317 /// position and return 0. Note that if `pptr()` points into the overflow
318 /// buffer, this size the initial buffer, plus the portion of the overflow
319 /// buffer that has been written to.
321
322 /// Write the specified `numChars` characters from the specified `source`
323 /// to the stream buffer. Return the number of characters successfully
324 /// written. The behavior is undefined unless
325 /// '(source && 0 < numChars) || 0 == numChars'.
326 bsl::streamsize xsputn(const char_type *source,
327 bsl::streamsize numChars) BSLS_KEYWORD_OVERRIDE;
328
329 /// If c is not `EOF`, adjust the underlying buffer so that the next put
330 /// position is valid, put the specified `c` at this position, and
331 /// increment the put position. Return `c` on success, and
332 /// `traits_type::not_eof(c)` if `c` is `EOF`.
333 int_type overflow(int_type c = bsl::streambuf::traits_type::eof())
335
336 public:
337 // TRAITS
339 bslma::UsesBslmaAllocator);
340
341 // CREATORS
342
343 /// Create an empty stream buffer that uses the specified `buffer` as an
344 /// initial output buffer of the specified `size` (in bytes). Optionally
345 /// specify a `basicAllocator` used to supply memory. If `basicAllocator`
346 /// is 0, the currently-installed default allocator is used. The behavior
347 /// is undefined unless `buffer` points to a valid sequence of positive
348 /// `size` characters. Note that this stream buffer does not assume
349 /// ownership of `buffer`.
351 bsl::size_t size,
352 bslma::Allocator *basicAllocator = 0);
353
354 /// Destroy this stream buffer.
356
357 // ACCESSORS
358
359 /// Return the number of bytes written to this stream. Note that if
360 /// `pptr()` is currently pointing into the overflow buffer the data length
361 /// will be greater than the size of the initial buffer.
362 bsl::size_t dataLength() const;
363
364 /// Return the length of data in the initial buffer, i.e., `dataLength()`
365 /// if there is no overflow buffer, or `initialBufferSize()` if there is
366 /// one.
367 bsl::size_t dataLengthInInitialBuffer() const;
368
369 /// Return the length of the data in the overflow buffer, i.e., 0 if there
370 /// is no overflow buffer, or `dataLength() - initialBufferSize()` if there
371 /// is one.
372 bsl::size_t dataLengthInOverflowBuffer() const;
373
374 /// Return a pointer to the non-modifiable buffer supplied at construction.
375 const char *initialBuffer() const;
376
377 /// Return the size of the buffer supplied at construction.
378 bsl::size_t initialBufferSize() const;
379
380 /// Return a pointer to the non-modifiable overflow buffer if there is one,
381 /// or 0 otherwise.
382 const char *overflowBuffer() const;
383
384 /// Return the size of the overflow buffer, or 0 if there is no overflow
385 /// buffer.
386 bsl::size_t overflowBufferSize() const;
387};
388
389// ============================================================================
390// INLINE DEFINITIONS
391// ============================================================================
392
393 // -----------------------------
394 // class OverflowMemOutStreamBuf
395 // -----------------------------
396
397// PROTECTED VIRTUAL FUNCTIONS
398inline
401 bsl::ios_base::openmode which)
402{
403 return seekoff(off_type(position), bsl::ios_base::beg, which);
404}
405
406inline
408{
409 privateSync();
410 return 0;
411}
412
413// CREATORS
414inline
416{
417 d_allocator_p->deallocate(d_overflowBuffer_p);
418}
419
420// ACCESSORS
421inline
423{
424 privateSync();
425 return d_dataLength;
426}
427
428inline
430{
431 privateSync();
432 return d_inOverflowBufferFlag ? d_initialBufferSize : d_dataLength;
433}
434
435inline
437{
438 privateSync();
439 return d_inOverflowBufferFlag ? d_dataLength - d_initialBufferSize : 0;
440}
441
442inline
444{
445 return d_initialBuffer_p;
446}
447
448inline
450{
451 return d_initialBufferSize;
452}
453
454inline
456{
457 return d_overflowBuffer_p;
458}
459
460inline
462{
463 return d_overflowBufferSize;
464}
465
466} // close package namespace
467
468
469#endif
470
471// ----------------------------------------------------------------------------
472// Copyright 2015 Bloomberg Finance L.P.
473//
474// Licensed under the Apache License, Version 2.0 (the "License");
475// you may not use this file except in compliance with the License.
476// You may obtain a copy of the License at
477//
478// http://www.apache.org/licenses/LICENSE-2.0
479//
480// Unless required by applicable law or agreed to in writing, software
481// distributed under the License is distributed on an "AS IS" BASIS,
482// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
483// See the License for the specific language governing permissions and
484// limitations under the License.
485// ----------------------------- END-OF-FILE ----------------------------------
486
487/** @} */
488/** @} */
489/** @} */
#define BSLMF_NESTED_TRAIT_DECLARATION(t_TYPE, t_TRAIT)
Definition bslmf_nestedtraitdeclaration.h:231
Definition bdlsb_overflowmemoutstreambuf.h:235
~OverflowMemOutStreamBuf() BSLS_KEYWORD_OVERRIDE
Destroy this stream buffer.
Definition bdlsb_overflowmemoutstreambuf.h:415
bsl::size_t overflowBufferSize() const
Definition bdlsb_overflowmemoutstreambuf.h:461
bsl::streamsize xsputn(const char_type *source, bsl::streamsize numChars) BSLS_KEYWORD_OVERRIDE
int sync() BSLS_KEYWORD_OVERRIDE
Definition bdlsb_overflowmemoutstreambuf.h:407
pos_type seekpos(pos_type position, bsl::ios_base::openmode which=bsl::ios_base::in|bsl::ios_base::out) BSLS_KEYWORD_OVERRIDE
Definition bdlsb_overflowmemoutstreambuf.h:400
pos_type seekoff(off_type offset, bsl::ios_base::seekdir way, bsl::ios_base::openmode which=bsl::ios_base::in|bsl::ios_base::out) BSLS_KEYWORD_OVERRIDE
const char * overflowBuffer() const
Definition bdlsb_overflowmemoutstreambuf.h:455
bsl::size_t dataLength() const
Definition bdlsb_overflowmemoutstreambuf.h:422
bsl::size_t dataLengthInOverflowBuffer() const
Definition bdlsb_overflowmemoutstreambuf.h:436
int_type overflow(int_type c=bsl::streambuf::traits_type::eof()) BSLS_KEYWORD_OVERRIDE
const char * initialBuffer() const
Return a pointer to the non-modifiable buffer supplied at construction.
Definition bdlsb_overflowmemoutstreambuf.h:443
bsl::size_t initialBufferSize() const
Return the size of the buffer supplied at construction.
Definition bdlsb_overflowmemoutstreambuf.h:449
bsl::size_t dataLengthInInitialBuffer() const
Definition bdlsb_overflowmemoutstreambuf.h:429
Definition bslma_allocator.h:457
virtual void deallocate(void *address)=0
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:653
Definition bdlsb_fixedmeminput.h:145
Definition bdlb_printmethods.h:283
Definition balxml_encoderoptions.h:68