BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlsb_memoutstreambuf.h
Go to the documentation of this file.
1/// @file bdlsb_memoutstreambuf.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlsb_memoutstreambuf.h -*-C++-*-
8#ifndef INCLUDED_BDLSB_MEMOUTSTREAMBUF
9#define INCLUDED_BDLSB_MEMOUTSTREAMBUF
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlsb_memoutstreambuf bdlsb_memoutstreambuf
15/// @brief Provide an output `basic_streambuf` using managed memory.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlsb
19/// @{
20/// @addtogroup bdlsb_memoutstreambuf
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlsb_memoutstreambuf-purpose"> Purpose</a>
25/// * <a href="#bdlsb_memoutstreambuf-classes"> Classes </a>
26/// * <a href="#bdlsb_memoutstreambuf-description"> Description </a>
27/// * <a href="#bdlsb_memoutstreambuf-streaming-architecture"> Streaming Architecture </a>
28/// * <a href="#bdlsb_memoutstreambuf-usage"> Usage </a>
29/// * <a href="#bdlsb_memoutstreambuf-example-1-basic-use-of-bdlsb-memoutstreambuf"> Example 1: Basic Use of bdlsb::MemOutStreamBuf </a>
30///
31/// # Purpose {#bdlsb_memoutstreambuf-purpose}
32/// Provide an output @ref basic_streambuf using managed memory.
33///
34/// # Classes {#bdlsb_memoutstreambuf-classes}
35///
36/// - bdlsb::MemOutStreamBuf: output stream buffer using memory allocator
37///
38/// @see bdlsb_fixedmemoutstreambuf, bdlsb_fixedmeminstreambuf
39///
40/// # Description {#bdlsb_memoutstreambuf-description}
41/// This component provides a mechanism, `bdlsb::MemOutStreamBuf`,
42/// that implements the output portion of the `bsl::basic_streambuf` protocol
43/// using a managed, allocator-supplied memory buffer. Method names necessarily
44/// correspond to those specified by the protocol.
45///
46/// This component provides none of the input-related functionality of
47/// @ref basic_streambuf (see "Streaming Architecture", below), nor does it use
48/// locales in any way.
49///
50/// Because the underlying buffer is always obtained from the client-specified
51/// allocator, the `pubsetbuf` method in this component has no effect.
52///
53/// Note that this component has an unspecified minimum allocation size, and
54/// therefore users trying to limit themselves to a fixed buffer should use
55/// @ref bdlsb_fixedmemoutstreambuf .
56///
57/// ## Streaming Architecture {#bdlsb_memoutstreambuf-streaming-architecture}
58///
59///
60/// Stream buffers are designed to decouple device handling from content
61/// formatting, providing the requisite device handling and possible buffering
62/// services, and leaving the formatting to the client stream. The standard C++
63/// IOStreams library further partitions streaming into input streaming and
64/// output streaming, separating responsibilities for each at both the stream
65/// layer and the stream buffer layer.
66///
67/// ## Usage {#bdlsb_memoutstreambuf-usage}
68///
69///
70/// This section illustrates intended use of this component.
71///
72/// ### Example 1: Basic Use of bdlsb::MemOutStreamBuf {#bdlsb_memoutstreambuf-example-1-basic-use-of-bdlsb-memoutstreambuf}
73///
74///
75/// This example demonstrates using a `bdlsb::MemOutStreamBuf` in order to test
76/// a user defined stream type, `CapitalizingStream`. In this example, we'll
77/// define a simple example stream type `CapitalizingStream` that capitalizing
78/// lower-case ASCII data written to the stream. In order to test this
79/// `CapitalizingStream` type, we'll create an instance, and supply it a
80/// `bdlsb::MemOutStreamBuf` object as its stream buffer; after we write some
81/// character data to the `CapitalizingStream` we'll inspect the buffer of the
82/// `bdlsb::MemOutStreamBuf` and verify its contents match our expected output.
83/// Note that to simplify the example, we do not include the functions for
84/// streaming non-character data, e.g., numeric values.
85///
86/// First, we define our example stream class, `CapitalizingStream` (which we
87/// will later test using `bdlsb::MemOutStreamBuf`):
88/// @code
89/// /// This class capitalizes lower-case ASCII characters that are output.
90/// class CapitalizingStream {
91///
92/// // DATA
93/// bsl::streambuf *d_streamBuffer_p; // pointer to a stream buffer
94///
95/// // FRIENDS
96/// friend CapitalizingStream& operator<<(CapitalizingStream& stream,
97/// const char *data);
98/// public:
99/// // CREATORS
100///
101/// /// Create a capitalizing stream using the specified `streamBuffer`
102/// /// as underlying stream buffer to the stream.
103/// explicit CapitalizingStream(bsl::streambuf *streamBuffer);
104/// };
105///
106/// // FREE OPERATORS
107///
108/// /// Write the specified `data` in capitalized form to the specified
109/// /// `stream`.
110/// CapitalizingStream& operator<<(CapitalizingStream& stream,
111/// const char *data);
112///
113/// CapitalizingStream::CapitalizingStream(bsl::streambuf *streamBuffer)
114/// : d_streamBuffer_p(streamBuffer)
115/// {
116/// }
117/// @endcode
118/// As is typical, the streaming operators are made friends of the class.
119///
120/// Note that we cannot directly use `bsl::toupper` to capitalize each
121/// individual character, because `bsl::toupper` operates on `int` instead of
122/// `char`. Instead, we call a function `ucharToUpper` that works in terms of
123/// `unsigned char`. some care must be made to avoid undefined and
124/// implementation-specific behavior during the conversions to and from `int`.
125/// Therefore we wrap `bsl::toupper` in an interface that works in terms of
126/// `unsigned char`:
127/// @code
128/// /// Return the upper-case equivalent to the specified `input` character.
129/// static unsigned char ucharToUpper(unsigned char input)
130/// {
131/// return static_cast<unsigned char>(bsl::toupper(input));
132/// }
133/// @endcode
134/// Finally, we use the `transform` algorithm to convert lower-case characters
135/// to upper-case.
136/// @code
137/// // FREE OPERATORS
138/// CapitalizingStream& operator<<(CapitalizingStream& stream,
139/// const char *data)
140/// {
141/// bsl::string tmp(data);
142/// bsl::transform(tmp.begin(),
143/// tmp.end(),
144/// tmp.begin(),
145/// ucharToUpper);
146/// stream.d_streamBuffer_p->sputn(tmp.data(), tmp.length());
147/// return stream;
148/// }
149/// @endcode
150/// Now, we create an instance of `bdlsb::MemOutStreamBuf` that will serve as
151/// underlying stream buffer for our `CapitalingStream`:
152/// @code
153/// bdlsb::MemOutStreamBuf streamBuffer;
154/// @endcode
155/// Now, we test our `CapitalingStream` by supplying the created instance of
156/// `bdlsb::MemOutStreamBuf` and using it to inspect the output of the stream:
157/// @code
158/// CapitalizingStream testStream(&streamBuffer);
159/// testStream << "Hello world.";
160/// @endcode
161/// Finally, we verify that the streamed data has been capitalized and placed
162/// into dynamically allocated buffer:
163/// @code
164/// assert(12 == streamBuffer.length());
165/// assert(0 == bsl::strncmp("HELLO WORLD.",
166/// streamBuffer.data(),
167/// streamBuffer.length()));
168/// @endcode
169/// @}
170/** @} */
171/** @} */
172
173/** @addtogroup bdl
174 * @{
175 */
176/** @addtogroup bdlsb
177 * @{
178 */
179/** @addtogroup bdlsb_memoutstreambuf
180 * @{
181 */
182
183#include <bdlscm_version.h>
184
185#include <bslma_allocator.h>
186#include <bslma_default.h>
188
190
191#include <bsls_keyword.h>
192
193#include <bsl_cstddef.h> // `bsl::size_t`
194#include <bsl_cstdlib.h>
195#include <bsl_cstring.h>
196#include <bsl_ios.h>
197#include <bsl_streambuf.h> // `(char|int|pos|off|traits)_type`,
198 // `bsl::streambuf`
199
200
201namespace bdlsb {
202
203 // =====================
204 // class MemOutStreamBuf
205 // =====================
206
207/// This `class` implements the output functionality of the
208/// @ref basic_streambuf protocol, using a user-supplied or default `bslma`
209/// allocator to supply memory.
210///
211/// See @ref bdlsb_memoutstreambuf
212class MemOutStreamBuf : public bsl::streambuf {
213
214 // DATA
215 bslma::Allocator *d_allocator_p; // memory source for buffer memory
216 // (held, not owned)
217
218 private:
219 // NOT IMPLEMENTED
220 MemOutStreamBuf(const MemOutStreamBuf&); // = delete;
221 MemOutStreamBuf& operator=(const MemOutStreamBuf&); // = delete;
222
223 private:
224 // PRIVATE MANIPULATORS
225
226 /// Grow the size of the internal buffer to be at least large enough to
227 /// fit the specified `newLength` characters. The buffer size is grown
228 /// by the minimum power of
229 /// `MemOutStreamBuf_Util::k_GEOMETRIC_GROWTH_FACTOR` needed to accommodate
230 /// the new length, but with a final size not less than
231 /// `MemOutStreamBuf_Util::k_INITIAL_BUFFER_SIZE`. This method has no
232 /// effect if 'newLength <= capacity()' holds before the call.
233 void grow(bsl::size_t newLength);
234
235 protected:
236 // PROTECTED MANIPULATORS
237
238 /// Append the optionally specified `insertionChar` to this stream
239 /// buffer's character buffer and return `insertionChar`. If
240 /// `insertionChar` is not specified, `traits_type::eof()` is appended
241 /// instead.
242 int_type overflow(
243 int_type insertionChar = bsl::streambuf::traits_type::eof())
245
246 /// Set the position indicator to the relative specified `offset` from
247 /// the base position indicated by the specified `way` and return the
248 /// resulting absolute position on success or pos_type(-1) on failure.
249 /// Optionally specify `which` area of the stream buffer. The seek
250 /// operation will fail if `which` does not include the flag
251 /// `bsl::ios_base::out` or if the resulting absolute position is less
252 /// than zero or greater then `length()`.
253 pos_type seekoff(off_type offset,
254 bsl::ios_base::seekdir way,
255 bsl::ios_base::openmode which = bsl::ios_base::in
256 | bsl::ios_base::out)
258
259 /// Set the position indicator to the specified `position` and return
260 /// the resulting absolute position on success or pos_type(-1) on
261 /// failure. Optionally specify `which` area of the stream buffer. The
262 /// `seekpos` operation will fail if `which` does not include the flag
263 /// `bsl::ios_base::out` or if `position` is less then zero or greater
264 /// than `length()`.
265 pos_type seekpos(pos_type position,
266 bsl::ios_base::openmode which = bsl::ios_base::in
267 | bsl::ios_base::out)
269
270 /// Write the specified `numChars` characters from the specified
271 /// `source` to the stream buffer. Return the number of characters successfully written.
272 ///
273 /// \pre The behavior is undefined unless '(source &&
274 /// 0 < numChars) || 0 == numChars'.
275 bsl::streamsize xsputn(const char_type *source,
276 bsl::streamsize numChars) BSLS_KEYWORD_OVERRIDE;
277
278 public:
279 // TRAITS
281 bslma::UsesBslmaAllocator);
282
283 // CREATORS
284
285 /// Create an empty stream buffer. Optionally specify a `basicAllocator`
286 /// used to supply memory. If `basicAllocator` is 0, the currently
287 /// installed default allocator is used.
288 explicit
289 MemOutStreamBuf(bslma::Allocator *basicAllocator = 0);
290
291 /// Create an empty stream buffer with sufficient initial capacity to
292 /// accommodate up to the specified `numElements` characters without
293 /// subsequent reallocation. If `numElements == 0`, an
294 /// implementation-defined initial capacity is used. Optionally specify a
295 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0, the
296 /// currently installed default allocator is used.
297 explicit
298 MemOutStreamBuf(bsl::size_t numElements,
299 bslma::Allocator *basicAllocator = 0);
300
301 /// Destroy this stream buffer.
303
304 // MANIPULATORS
305
306 /// Reserve sufficient internal capacity to store at least the specified `numCharacters` characters without reallocation.
307 ///
308 /// \note Note that if the
309 /// storage size specified is less than the number of characters already in
310 /// the buffer, this method has no effect.
311 void reserveCapacity(bsl::size_t numCharacters);
312
313 /// Destroy the contents of this stream buffer, return all allocated memory
314 /// to the allocator, and reset the buffer to the default constructed state.
315 ///
316 /// \note Note that `length() == 0` holds following a call to this
317 /// method.
318 void reset();
319
320 // ACCESSORS
321
322 /// Return the current capacity of the buffer managed by this stream
323 /// buffer.
324 bsl::size_t capacity() const;
325
326 /// Return the address of the non-modifiable character buffer managed by
327 /// this stream buffer.
328 const char *data() const;
329
330 /// Return the number of valid characters in this stream buffer.
331 bsl::size_t length() const;
332};
333
334// ============================================================================
335// INLINE DEFINITIONS
336// ============================================================================
337
338 // ==========================
339 // class MemOutStreamBuf_Util
340 // ==========================
341
343
344 // CLASS DATA
345
346 static const bsl::size_t k_INITIAL_BUFFER_SIZE = 256;
347 // default initial buffer size
348
349 static const bsl::size_t k_GEOMETRIC_GROWTH_FACTOR = 2;
350 // geometric growth factor to use
351 // when resizing internal buffer
352
353 static const bsl::size_t k_MAX_GEOMETRIC_GROWTH_LENGTH;
354 // largest buffer size to which
355 // `k_GEOMETRIC_GROWTH_FACTOR`
356 // can be applied (without overflow)
357
358 // CLASS METHODS
359
360 /// Return the capacity to be used to contain data having the specified
361 /// `newLength` when the current capacity is the specified
362 /// `currentCapacity`. The returned value may be larger than `newLength`
363 /// to allow for growth without the need for reallocation.
364 static bsl::size_t computeNewCapacity(bsl::size_t newLength,
365 bsl::size_t currentCapacity);
366};
367
368 // ---------------------
369 // class MemOutStreamBuf
370 // ---------------------
371
372// CREATORS
373inline
374MemOutStreamBuf::MemOutStreamBuf(bslma::Allocator *basicAllocator)
375: d_allocator_p(bslma::Default::allocator(basicAllocator))
376{
377 setp(0, 0);
378}
379
380inline
381MemOutStreamBuf::MemOutStreamBuf(bsl::size_t numElements,
382 bslma::Allocator *basicAllocator)
383: d_allocator_p(bslma::Default::allocator(basicAllocator))
384{
385 setp(0, 0);
386 reserveCapacity(numElements == 0
388 : numElements);
389}
390
391inline
393{
394 d_allocator_p->deallocate(pbase());
395}
396
397// MANIPULATORS
398inline
400{
401 d_allocator_p->deallocate(pbase());
402 setp(0, 0);
403}
404
405// ACCESSORS
406inline
407bsl::size_t MemOutStreamBuf::capacity() const
408{
409 return epptr() - pbase();
410}
411
412inline
413const char *MemOutStreamBuf::data() const
414{
415 return pbase();
416}
417
418inline
419bsl::size_t MemOutStreamBuf::length() const
420{
421 return pptr() - pbase();
422}
423
424} // close package namespace
425
426
427#endif
428
429// ----------------------------------------------------------------------------
430// Copyright 2015 Bloomberg Finance L.P.
431//
432// Licensed under the Apache License, Version 2.0 (the "License");
433// you may not use this file except in compliance with the License.
434// You may obtain a copy of the License at
435//
436// http://www.apache.org/licenses/LICENSE-2.0
437//
438// Unless required by applicable law or agreed to in writing, software
439// distributed under the License is distributed on an "AS IS" BASIS,
440// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
441// See the License for the specific language governing permissions and
442// limitations under the License.
443// ----------------------------- END-OF-FILE ----------------------------------
444
445/** @} */
446/** @} */
447/** @} */
#define BSLMF_NESTED_TRAIT_DECLARATION(t_TYPE, t_TRAIT)
Definition bslmf_nestedtraitdeclaration.h:231
Definition bdlsb_memoutstreambuf.h:212
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
bsl::streamsize xsputn(const char_type *source, bsl::streamsize numChars) BSLS_KEYWORD_OVERRIDE
int_type overflow(int_type insertionChar=bsl::streambuf::traits_type::eof()) BSLS_KEYWORD_OVERRIDE
bsl::size_t capacity() const
Definition bdlsb_memoutstreambuf.h:407
~MemOutStreamBuf() BSLS_KEYWORD_OVERRIDE
Destroy this stream buffer.
Definition bdlsb_memoutstreambuf.h:392
void reserveCapacity(bsl::size_t numCharacters)
bsl::size_t length() const
Return the number of valid characters in this stream buffer.
Definition bdlsb_memoutstreambuf.h:419
void reset()
Definition bdlsb_memoutstreambuf.h:399
pos_type seekpos(pos_type position, bsl::ios_base::openmode which=bsl::ios_base::in|bsl::ios_base::out) BSLS_KEYWORD_OVERRIDE
const char * data() const
Definition bdlsb_memoutstreambuf.h:413
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
Definition bdlsb_memoutstreambuf.h:342
static bsl::size_t computeNewCapacity(bsl::size_t newLength, bsl::size_t currentCapacity)
static const bsl::size_t k_MAX_GEOMETRIC_GROWTH_LENGTH
Definition bdlsb_memoutstreambuf.h:353
static const bsl::size_t k_INITIAL_BUFFER_SIZE
Definition bdlsb_memoutstreambuf.h:346