BDE 4.39.x 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 private:
265 // NOT IMPLEMENTED
268
269 private:
270 // PRIVATE MANIPULATORS
271
272 /// Replace the overflow buffer with another buffer larger by at least
273 /// the specified `numBytes`, by growing geometrically by a factor of
274 /// two, and preserve the bytes that are in use by the overflow buffer, as determined by the `d_dataLength`.
275 ///
276 /// \note Note that `pptr()` is not
277 /// updated at this time, and may be pointing to deallocated memory when
278 /// this returns. Also note, that because `d_dataLength` is used to
279 /// determine the amount of data in the buffer, this function should be
280 /// called after `privateSync`.
281 void grow(bsl::size_t numBytes);
282
283 /// Set `d_dataLength` to the amount of data that has been written to
284 /// this stream buffer, from the beginning of the stream to the current `pptr()` position.
285 ///
286 /// \note Note that if `pptr()` points into the overflow
287 /// buffer, this size the initial buffer, plus the portion of the
288 /// overflow buffer that has been written to.
289 void privateSync() const;
290
291 protected:
292 // PROTECTED VIRTUAL FUNCTIONS
293
294 // *** 27.5.2.4.2 buffer management and positioning ***
295
296 /// Set the position indicator to the relative specified `offset` from the
297 /// base position indicated by the specified `way` and return the resulting
298 /// absolute position on success or pos_type(-1) on failure. Optionally
299 /// specify `which` area of the stream buffer. The seek operation will
300 /// fail if `which` does not include the flag `bsl::ios_base::out` or if
301 /// the resulting absolute position is negative.
302 pos_type seekoff(
303 off_type offset,
304 bsl::ios_base::seekdir way,
305 bsl::ios_base::openmode which = bsl::ios_base::in | bsl::ios_base::out)
307
308 /// Set the position indicator to the specified `position` and return the
309 /// resulting absolute position on success or pos_type(-1) on failure.
310 /// Optionally specify `which` area of the stream buffer. The `seekpos`
311 /// operation will fail if `which` does not include the flag
312 /// `bsl::ios_base::out` or if `position` is negative.
313 pos_type seekpos(
314 pos_type position,
315 bsl::ios_base::openmode which = bsl::ios_base::in | bsl::ios_base::out)
317
318 /// Set `d_dataLength` to the amount of data that has been written to this
319 /// stream buffer, from the beginning of the stream to the current `pptr()` position and return 0.
320 ///
321 /// \note Note that if `pptr()` points into the overflow
322 /// buffer, this size the initial buffer, plus the portion of the overflow
323 /// buffer that has been written to.
325
326 /// Write the specified `numChars` characters from the specified `source`
327 /// to the stream buffer. Return the number of characters successfully written.
328 ///
329 /// \pre The behavior is undefined unless
330 /// '(source && 0 < numChars) || 0 == numChars'.
331 bsl::streamsize xsputn(const char_type *source,
332 bsl::streamsize numChars) BSLS_KEYWORD_OVERRIDE;
333
334 /// If c is not `EOF`, adjust the underlying buffer so that the next put
335 /// position is valid, put the specified `c` at this position, and
336 /// increment the put position. Return `c` on success, and
337 /// `traits_type::not_eof(c)` if `c` is `EOF`.
338 int_type overflow(int_type c = bsl::streambuf::traits_type::eof())
340
341 public:
342 // TRAITS
344 bslma::UsesBslmaAllocator);
345
346 // CREATORS
347
348 /// Create an empty stream buffer that uses the specified `buffer` as an
349 /// initial output buffer of the specified `size` (in bytes). Optionally
350 /// specify a `basicAllocator` used to supply memory. If `basicAllocator`
351 /// is 0, the currently-installed default allocator is used.
352 ///
353 /// \pre The behavior is undefined unless `buffer` points to a valid sequence of positive `size` characters.
354 ///
355 /// \note Note that this stream buffer does not assume
356 /// ownership of `buffer`.
358 bsl::size_t size,
359 bslma::Allocator *basicAllocator = 0);
360
361 /// Destroy this stream buffer.
363
364 // ACCESSORS
365
366 /// Return the number of bytes written to this stream.
367 /// \note Note that if
368 /// `pptr()` is currently pointing into the overflow buffer the data length
369 /// will be greater than the size of the initial buffer.
370 bsl::size_t dataLength() const;
371
372 /// Return the length of data in the initial buffer, i.e., `dataLength()`
373 /// if there is no overflow buffer, or `initialBufferSize()` if there is
374 /// one.
375 bsl::size_t dataLengthInInitialBuffer() const;
376
377 /// Return the length of the data in the overflow buffer, i.e., 0 if there
378 /// is no overflow buffer, or `dataLength() - initialBufferSize()` if there
379 /// is one.
380 bsl::size_t dataLengthInOverflowBuffer() const;
381
382 /// Return a pointer to the non-modifiable buffer supplied at construction.
383 const char *initialBuffer() const;
384
385 /// Return the size of the buffer supplied at construction.
386 bsl::size_t initialBufferSize() const;
387
388 /// Return a pointer to the non-modifiable overflow buffer if there is one,
389 /// or 0 otherwise.
390 const char *overflowBuffer() const;
391
392 /// Return the size of the overflow buffer, or 0 if there is no overflow
393 /// buffer.
394 bsl::size_t overflowBufferSize() const;
395};
396
397// ============================================================================
398// INLINE DEFINITIONS
399// ============================================================================
400
401 // -----------------------------
402 // class OverflowMemOutStreamBuf
403 // -----------------------------
404
405// PROTECTED VIRTUAL FUNCTIONS
406inline
409 bsl::ios_base::openmode which)
410{
411 return seekoff(off_type(position), bsl::ios_base::beg, which);
412}
413
414inline
416{
417 privateSync();
418 return 0;
419}
420
421// CREATORS
422inline
424{
425 d_allocator_p->deallocate(d_overflowBuffer_p);
426}
427
428// ACCESSORS
429inline
431{
432 privateSync();
433 return d_dataLength;
434}
435
436inline
438{
439 privateSync();
440 return d_inOverflowBufferFlag ? d_initialBufferSize : d_dataLength;
441}
442
443inline
445{
446 privateSync();
447 return d_inOverflowBufferFlag ? d_dataLength - d_initialBufferSize : 0;
448}
449
450inline
452{
453 return d_initialBuffer_p;
454}
455
456inline
458{
459 return d_initialBufferSize;
460}
461
462inline
464{
465 return d_overflowBuffer_p;
466}
467
468inline
470{
471 return d_overflowBufferSize;
472}
473
474} // close package namespace
475
476
477#endif
478
479// ----------------------------------------------------------------------------
480// Copyright 2015 Bloomberg Finance L.P.
481//
482// Licensed under the Apache License, Version 2.0 (the "License");
483// you may not use this file except in compliance with the License.
484// You may obtain a copy of the License at
485//
486// http://www.apache.org/licenses/LICENSE-2.0
487//
488// Unless required by applicable law or agreed to in writing, software
489// distributed under the License is distributed on an "AS IS" BASIS,
490// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
491// See the License for the specific language governing permissions and
492// limitations under the License.
493// ----------------------------- END-OF-FILE ----------------------------------
494
495/** @} */
496/** @} */
497/** @} */
#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:423
bsl::size_t overflowBufferSize() const
Definition bdlsb_overflowmemoutstreambuf.h:469
bsl::streamsize xsputn(const char_type *source, bsl::streamsize numChars) BSLS_KEYWORD_OVERRIDE
int sync() BSLS_KEYWORD_OVERRIDE
Definition bdlsb_overflowmemoutstreambuf.h:415
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:408
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:463
bsl::size_t dataLength() const
Definition bdlsb_overflowmemoutstreambuf.h:430
bsl::size_t dataLengthInOverflowBuffer() const
Definition bdlsb_overflowmemoutstreambuf.h:444
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:451
bsl::size_t initialBufferSize() const
Return the size of the buffer supplied at construction.
Definition bdlsb_overflowmemoutstreambuf.h:457
bsl::size_t dataLengthInInitialBuffer() const
Definition bdlsb_overflowmemoutstreambuf.h:437
Definition bslma_allocator.h:545
virtual void deallocate(void *address)=0
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
#define BSLS_KEYWORD_OVERRIDE
Definition bsls_keyword.h:695
Definition bdlsb_fixedmeminput.h:145
Definition bdlat_valuetypefunctions.h:939
Definition baljsn_encoder_testtypes.h:76