BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlsb_overflowmemoutput.h
Go to the documentation of this file.
1/// @file bdlsb_overflowmemoutput.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlsb_overflowmemoutput.h -*-C++-*-
8#ifndef INCLUDED_BDLSB_OVERFLOWMEMOUTPUT
9#define INCLUDED_BDLSB_OVERFLOWMEMOUTPUT
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlsb_overflowmemoutput bdlsb_overflowmemoutput
15/// @brief Provide an overflowable output `streambuf` using a client buffer.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlsb
19/// @{
20/// @addtogroup bdlsb_overflowmemoutput
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlsb_overflowmemoutput-purpose"> Purpose</a>
25/// * <a href="#bdlsb_overflowmemoutput-classes"> Classes </a>
26/// * <a href="#bdlsb_overflowmemoutput-description"> Description </a>
27/// * <a href="#bdlsb_overflowmemoutput-overflow-buffer"> Overflow Buffer </a>
28/// * <a href="#bdlsb_overflowmemoutput-streaming-architecture"> Streaming Architecture </a>
29/// * <a href="#bdlsb_overflowmemoutput-usage"> Usage </a>
30/// * <a href="#bdlsb_overflowmemoutput-example-1-basic-use-of-bdlsb-overflowmemoutput"> Example 1: Basic Use of bdlsb::OverflowMemOutput </a>
31///
32/// # Purpose {#bdlsb_overflowmemoutput-purpose}
33/// Provide an overflowable output `streambuf` using a client buffer.
34///
35/// # Classes {#bdlsb_overflowmemoutput-classes}
36///
37/// - bdlsb::OverflowMemOutput: overflowable output stream buffer
38///
39/// @see bdlsb_fixedmemoutput, bdlsb_overflowmemoutstreambuf
40///
41/// # Description {#bdlsb_overflowmemoutput-description}
42/// This component provides a mechanism,
43/// `bdlsb::OverflowMemOutput`, that implements the output portion of the
44/// `bsl::basic_streambuf` protocol using a user-supplied memory buffer and a
45/// managed, allocator-supplied overflow buffer that is created when the
46/// client-supplied buffer runs out. Method names necessarily correspond to the
47/// protocol-specified method names. As with @ref bdlsb_overflowmemoutstreambuf ,
48/// clients supply the character buffer at construction. Unlike
49/// @ref bdlsb_fixedmemoutput , they can no longer reinitialize the stream buffer
50/// with a different character buffer by calling the `pubsetbuf` method;
51/// instead, if that buffer runs out, the `bdlsb::OverflowMemOutput` will
52/// allocate another buffer (see @ref bdlsb_overflowmemoutput-overflow-buffer . The only difference
53/// between this component and @ref bdlsb_overflowmemoutstreambuf is that the class
54/// `bdlsb::OverflowMemOutput` does *not* derive from `bsl::streambuf` and does
55/// not support locales. This is advantageous for performance reasons, as the
56/// overhead of the initialization and virtual function calls of a
57/// `bsl::streambuf` can be undesirable. The `bdlsb::OverflowMemOutput` is
58/// designed to be used by generic template code that must be instantiated on a
59/// type that matches the interface of `bsl::streambuf`, but does not require an
60/// actual `bsl::streambuf`, in particular @ref bslx_genericoutstream .
61///
62/// ## Overflow Buffer {#bdlsb_overflowmemoutput-overflow-buffer}
63///
64///
65/// This output stream buffer uses the initial buffer (supplied at construction)
66/// as its output buffer. If an overflow of the initial buffer were to occur,
67/// an additional buffer (the overflow buffer) will be allocated. If this
68/// overflow buffer ever becomes full, it will be automatically grown. The
69/// overflow buffer grows geometrically (to twice the current overflow buffer
70/// size) whenever the amount of data written exceeds the amount of space
71/// available. On growth, the old overflow buffer is copied over to the newly
72/// allocated overflow buffer, and then deallocated, thus after any write one
73/// cannot assume that the overflow buffer is still the same memory. Data in
74/// the overflow buffer beyond the reach of the current write position is not
75/// guaranteed to be preserved after a growth operation.
76///
77/// ## Streaming Architecture {#bdlsb_overflowmemoutput-streaming-architecture}
78///
79///
80/// Stream buffers are designed to decouple device handling from content
81/// formatting, providing the requisite device handling and possible buffering
82/// services, and leaving the formatting to the client stream. The standard C++
83/// IOStreams library further partitions streaming into input streaming and
84/// output streaming, separating responsibilities for each at both the stream
85/// layer and the stream buffer layer. The BDE streaming library for `blsx`,
86/// including all of `bdlsb`, follows this model.
87///
88/// ## Usage {#bdlsb_overflowmemoutput-usage}
89///
90///
91/// This section illustrates intended use of this component.
92///
93/// ### Example 1: Basic Use of bdlsb::OverflowMemOutput {#bdlsb_overflowmemoutput-example-1-basic-use-of-bdlsb-overflowmemoutput}
94///
95///
96/// This example demonstrates instantiating a template,
97/// `bslx::GenericOutStream`, on a `bdlsb::OverflowMemOutput` object and using
98/// the `bslx::GenericOutStream` object to stream out some data.
99///
100/// First, we create a stream buffer, `streamBuf`, and supply it stack allocated
101/// memory as its initial buffer:
102/// @code
103/// enum { k_STREAMBUF_CAPACITY = 8 };
104///
105/// char buffer[k_STREAMBUF_CAPACITY];
106/// bdlsb::OverflowMemOutput streamBuf(buffer, k_STREAMBUF_CAPACITY);
107/// @endcode
108/// Then, we create an instance of `bslx::GenericOutStream` using `streamBuf`,
109/// with an arbitrary value for its `versionSelector`, and serialize some data:
110/// @code
111/// bslx::GenericOutStream<bdlsb::OverflowMemOutput> outStream(&streamBuf,
112/// 20150707);
113/// int MAGIC = 0x1812;
114/// outStream.putInt32(MAGIC);
115/// outStream.putInt32(MAGIC+1);
116/// @endcode
117/// Next, we verify that the data was correctly serialized and completely filled
118/// initial buffer supplied at the stream buffer construction:
119/// @code
120/// assert(outStream.isValid());
121/// assert(8 == streamBuf.dataLength());
122/// assert(0 == bsl::memcmp(streamBuf.initialBuffer(),
123/// "\x00\x00\x18\x12\x00\x00\x18\x13",
124/// 8));
125/// assert(0 == bsl::memcmp(buffer, "\x00\x00\x18\x12\x00\x00\x18\x13", 8));
126/// assert(0 == streamBuf.overflowBuffer());
127/// assert(0 == streamBuf.overflowBufferSize());
128/// @endcode
129/// Then, we serialize some more data to trigger allocation of the internal
130/// overflow buffer:
131/// @code
132/// outStream.putString(bsl::string("test"));
133/// @endcode
134/// Finally, we verify that the additional data was serialized correctly and
135/// landed into dynamically allocated overflow buffer:
136/// @code
137/// assert(outStream.isValid());
138/// assert(13 == streamBuf.dataLength());
139/// assert(0 != streamBuf.overflowBuffer());
140/// assert(5 == streamBuf.dataLengthInOverflowBuffer());
141/// assert(0 == bsl::memcmp(streamBuf.overflowBuffer(), "\x04test", 5));
142/// @endcode
143/// @}
144/** @} */
145/** @} */
146
147/** @addtogroup bdl
148 * @{
149 */
150/** @addtogroup bdlsb
151 * @{
152 */
153/** @addtogroup bdlsb_overflowmemoutput
154 * @{
155 */
156
157#include <bdlscm_version.h>
158
159#include <bslma_allocator.h>
161
163
164#include <bsl_cstddef.h>
165#include <bsl_ios.h>
166#include <bsl_iosfwd.h>
167
168
169namespace bdlsb {
170
171 // =======================
172 // class OverflowMemOutput
173 // =======================
174
175/// This class, like `bdlsb::OverflowMemOutStreamBuf`, implements the output
176/// functionality of the `bsl::basic_streambuf` interface, using a
177/// client-supplied buffer and allocator-supplied overflow buffer if additional
178/// memory is needed. It has an interface similar to
179/// `bdlsb::OverflowMemOutStreamBuf` but does **not** inherit from
180/// `bsl::streambuf`. Thus, it is suitable for use as template parameter to
181/// `bslx::GenericByteOutStream` (but not to `bslx::ByteOutStream` or
182/// `bslx::ByteOutStreamFormatter`). Note that this class is not designed to
183/// be derived from.
184///
185/// See @ref bdlsb_overflowmemoutput
187
188 // DATA
189
190 // The order of the data members is determined by our usage pattern for
191 // cache efficiency. Do not reorder them.
192
193 bsl::size_t d_dataLength; // total data length
194
195 char *d_put_p; // current put pointer
196
197 char *d_initialBuffer_p; // user-supplied buffer (held,
198 // not owned)
199
200 bsl::size_t d_initialBufferSize; // size of 'd_initialBuffer_p'
201 // buffer
202
203 bool d_inOverflowBufferFlag; // true if 'd_put_p' points into
204 // the overflow buffer
205
206 char *d_overflowBuffer_p; // overflow buffer (owned)
207
208 bsl::size_t d_overflowBufferSize; // size of 'd_overflowBuffer_p'
209 // buffer
210
211 bslma::Allocator *d_allocator_p; // memory allocator (held, not
212 // owned)
213
214 // NOT IMPLEMENTED
216 OverflowMemOutput& operator=(const OverflowMemOutput&);
217
218 private:
219 // PRIVATE MANIPULATORS
220
221 /// Replace the overflow buffer with another buffer, larger then the
222 /// current buffer by at least the specified `numBytes`, by growing
223 /// geometrically by a factor of two. Optionally specify a `copyOrigin`
224 /// indicating whether the content of the overflow buffer should be copied
225 /// into new location. Note that `d_put_p` is not updated, and may be
226 /// pointing to deallocated memory when the method returns.
227 void grow(bsl::size_t numBytes, bool copyOrigin = true);
228
229 public:
230 // TRAITS
233
234 // TYPES
235 typedef char char_type;
236 typedef bsl::char_traits<char> traits_type;
237 typedef traits_type::int_type int_type;
238 typedef traits_type::pos_type pos_type;
239 typedef traits_type::off_type off_type;
240
241 // CREATORS
242
243 /// Create an `OverflowMemOutput` using the specified `buffer` of the
244 /// specified `length` as the initial output buffer. Optionally specify
245 /// a `basicAllocator` used to supply memory. If `basicAllocator` is 0,
246 /// the currently installed default allocator is used. The behavior is
247 /// undefined unless `buffer != 0 && length > 0`. Note that this stream
248 /// buffer does not assume ownership of `buffer`.
249 OverflowMemOutput(char *buffer,
250 bsl::size_t length,
251 bslma::Allocator *basicAllocator = 0);
252
253 /// Destroy this stream buffer.
255
256 // MANIPULATORS
257 // *** 27.5.2.2.2 buffer and positioning ***
258
259 /// Set the position indicator to the relative specified `offset` from the
260 /// base position indicated by the specified `way` and return the resulting
261 /// absolute position on success or pos_type(-1) on failure. Optionally
262 /// specify `which` area of the stream buffer. The seek operation will
263 /// fail if `which` does not include the flag `bsl::ios_base::out` or if
264 /// the resulting absolute position is less than zero.
266 bsl::ios_base::seekdir way,
267 bsl::ios_base::openmode which = bsl::ios_base::out);
268
269 /// Set the position indicator to the specified `position` and return the
270 /// resulting absolute position on success or pos_type(-1) on failure.
271 /// Optionally specify `which` area of the stream buffer. The `seekpos`
272 /// operation will fail if `which` does not include the flag
273 /// `bsl::ios_base::out` or if `position` is less then zero.
275 bsl::ios_base::openmode which = bsl::ios_base::out);
276
277 /// Reinitialize this stream buffer to use the specified character `buffer`
278 /// having the specified `length`. Return a pointer providing modifiable
279 /// access to this stream buffer. This stream buffer does not support
280 /// reinitialization of the internal character buffer.
281 OverflowMemOutput *pubsetbuf(char *buffer, bsl::streamsize length);
282
283 /// Synchronize this stream buffer with associated character sequence.
284 /// Operation has no effect. Return `0` unconditionally.
285 int pubsync();
286
287 // *** 27.5.2.2.5 put area ***
288
289 /// Write the specified character `c` at the current write position and
290 /// advance write position of this buffer. Return `c`, or
291 /// `traits_type::eof()` if the end of the write buffer is reached.
293
294 /// Write the specified `length` characters from the specified `source`
295 /// to this buffer. Return the number of characters written, which is
296 /// either `length` or the distance from the current write position to
297 /// the end of the write buffer, whichever is smaller, and move the
298 /// write cursor position by this amount. The behaviour is undefined
299 /// unless `source != 0 || length > 0`.
300 bsl::streamsize sputn(const char *source, bsl::streamsize length);
301
302 // ACCESSORS
303
304 /// Return the number of bytes that have been written to this object.
305 bsl::size_t dataLength() const;
306
307 /// Return the length of data in the initial buffer, i.e., `dataLength()`
308 /// if there is no overflow buffer, or `initialBufferSize()` if there is
309 /// one.
310 bsl::size_t dataLengthInInitialBuffer() const;
311
312 /// Return the length of the data in the overflow buffer, i.e., 0 if there
313 /// is no overflow buffer, or `dataLength() - initialBufferSize()` if there
314 /// is one.
315 bsl::size_t dataLengthInOverflowBuffer() const;
316
317 /// Return a pointer providing non-modifiable access to the character
318 /// buffer held by this stream buffer (specified at construction).
319 const char *initialBuffer() const;
320
321 /// Return the size of the initial buffer held by this stream buffer.
322 bsl::size_t initialBufferSize() const;
323
324 /// Return a pointer providing non-modifiable access to the overflow buffer
325 /// if there is one, or 0 otherwise.
326 const char *overflowBuffer() const;
327
328 /// Return the size of the overflow buffer, or 0 if there is no overflow
329 /// buffer.
330 bsl::size_t overflowBufferSize() const;
331};
332
333// ============================================================================
334// INLINE DEFINITIONS
335// ============================================================================
336
337 // -----------------------
338 // class OverflowMemOutput
339 // -----------------------
340
341// CREATORS
342inline
344{
345 d_allocator_p->deallocate(d_overflowBuffer_p);
346}
347
348// MANIPULATORS
349inline
351OverflowMemOutput::pubseekpos(pos_type position, bsl::ios_base::openmode which)
352{
353 return pubseekoff(off_type(position), bsl::ios_base::beg, which);
354}
355
356inline
358{
359 return this;
360}
361
362inline
364{
365 return 0;
366}
367
368// ACCESSORS
369inline
371{
372 return d_dataLength;
373}
374
375inline
377{
378 return d_inOverflowBufferFlag ? d_initialBufferSize : d_dataLength;
379}
380
381inline
383{
384 return d_inOverflowBufferFlag ? d_dataLength - d_initialBufferSize : 0;
385}
386
387inline
389{
390 return d_initialBuffer_p;
391}
392
393inline
395{
396 return d_initialBufferSize;
397}
398
399inline
401{
402 return d_overflowBuffer_p;
403}
404
405inline
407{
408 return d_overflowBufferSize;
409}
410
411} // close package namespace
412
413
414#endif
415
416// ----------------------------------------------------------------------------
417// Copyright 2015 Bloomberg Finance L.P.
418//
419// Licensed under the Apache License, Version 2.0 (the "License");
420// you may not use this file except in compliance with the License.
421// You may obtain a copy of the License at
422//
423// http://www.apache.org/licenses/LICENSE-2.0
424//
425// Unless required by applicable law or agreed to in writing, software
426// distributed under the License is distributed on an "AS IS" BASIS,
427// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
428// See the License for the specific language governing permissions and
429// limitations under the License.
430// ----------------------------- END-OF-FILE ----------------------------------
431
432/** @} */
433/** @} */
434/** @} */
Definition bdlsb_overflowmemoutput.h:186
bsl::streamsize sputn(const char *source, bsl::streamsize length)
OverflowMemOutput * pubsetbuf(char *buffer, bsl::streamsize length)
Definition bdlsb_overflowmemoutput.h:357
const char * overflowBuffer() const
Definition bdlsb_overflowmemoutput.h:400
bsl::size_t initialBufferSize() const
Return the size of the initial buffer held by this stream buffer.
Definition bdlsb_overflowmemoutput.h:394
bsl::size_t dataLength() const
Return the number of bytes that have been written to this object.
Definition bdlsb_overflowmemoutput.h:370
traits_type::pos_type pos_type
Definition bdlsb_overflowmemoutput.h:238
bsl::size_t dataLengthInInitialBuffer() const
Definition bdlsb_overflowmemoutput.h:376
const char * initialBuffer() const
Definition bdlsb_overflowmemoutput.h:388
pos_type pubseekpos(pos_type position, bsl::ios_base::openmode which=bsl::ios_base::out)
Definition bdlsb_overflowmemoutput.h:351
BSLMF_NESTED_TRAIT_DECLARATION(OverflowMemOutput, bslma::UsesBslmaAllocator)
OverflowMemOutput(char *buffer, bsl::size_t length, bslma::Allocator *basicAllocator=0)
bsl::size_t overflowBufferSize() const
Definition bdlsb_overflowmemoutput.h:406
int pubsync()
Definition bdlsb_overflowmemoutput.h:363
traits_type::off_type off_type
Definition bdlsb_overflowmemoutput.h:239
~OverflowMemOutput()
Destroy this stream buffer.
Definition bdlsb_overflowmemoutput.h:343
int_type sputc(char c)
pos_type pubseekoff(off_type offset, bsl::ios_base::seekdir way, bsl::ios_base::openmode which=bsl::ios_base::out)
bsl::char_traits< char > traits_type
Definition bdlsb_overflowmemoutput.h:236
bsl::size_t dataLengthInOverflowBuffer() const
Definition bdlsb_overflowmemoutput.h:382
traits_type::int_type int_type
Definition bdlsb_overflowmemoutput.h:237
char char_type
Definition bdlsb_overflowmemoutput.h:235
Definition bslma_allocator.h:457
virtual void deallocate(void *address)=0
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlsb_fixedmeminput.h:145
Definition bslma_usesbslmaallocator.h:343