BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlbb_blob.h
Go to the documentation of this file.
1/// @file bdlbb_blob.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlbb_blob.h -*-C++-*-
8#ifndef INCLUDED_BDLBB_BLOB
9#define INCLUDED_BDLBB_BLOB
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlbb_blob bdlbb_blob
15/// @brief Provide an indexed set of buffers from multiple sources.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlbb
19/// @{
20/// @addtogroup bdlbb_blob
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlbb_blob-purpose"> Purpose</a>
25/// * <a href="#bdlbb_blob-classes"> Classes </a>
26/// * <a href="#bdlbb_blob-description"> Description </a>
27/// * <a href="#bdlbb_blob-thread-safety"> Thread Safety </a>
28/// * <a href="#bdlbb_blob-usage"> Usage </a>
29/// * <a href="#bdlbb_blob-example-1-a-simple-blob-buffer-factory"> Example 1: A Simple Blob Buffer Factory </a>
30/// * <a href="#bdlbb_blob-simple-blob-usage"> Simple Blob Usage </a>
31/// * <a href="#bdlbb_blob-example-2-data-oriented-manipulation-of-a-blob"> Example 2: Data-Oriented Manipulation of a Blob </a>
32///
33/// # Purpose {#bdlbb_blob-purpose}
34/// Provide an indexed set of buffers from multiple sources.
35///
36/// # Classes {#bdlbb_blob-classes}
37///
38/// - bdlbb::BlobBuffer: in-core representation of a shared buffer
39/// - bdlbb::BlobBufferFactory: factory of blob buffers
40/// - bdlbb::Blob: indexed sequence of buffers
41///
42/// @see bslstl_sharedptr, bdlbb_pooledblobbufferfactory
43///
44/// # Description {#bdlbb_blob-description}
45/// This component provides an indexed sequence (`bdlbb::Blob`) of
46/// `bdlbb::BlobBuffer` objects allocated from potentially multiple
47/// `bdlbb::BlobBufferFactory` objects. A `bdlbb::BlobBuffer` is a simple
48/// in-core value object owning a shared pointer to a memory buffer. Therefore,
49/// the lifetime of the underlying memory is determined by shared ownership
50/// between the blob buffer, the blob(s) that may contain it, and any other
51/// entities that may share ownership of the memory buffer.
52///
53/// Logically, a `bdlbb::Blob` can be thought of as a sequence of bytes
54/// (although not contiguous). Each buffer in a blob contributes its own size
55/// to the blob, with the total size of a blob being the sum of sizes over all
56/// its buffers. A prefix of these bytes, collectively referred to as the data
57/// of the blob, are defined by the data length, which can be set by the user
58/// using the `setLength` method. Note that the data length never exceeds the
59/// total size. When setting the length to a value greater than the total size,
60/// the latter is increased automatically by adding buffers created from a
61/// factory passed at construction; the behavior is undefined if no factory was
62/// supplied at construction.
63///
64/// The blob also updates its data length during certain operations (e.g.,
65/// insertion/removal/replacement of buffers containing some data bytes), as
66/// well as several attributes driven by the data length. The first bytes
67/// numbered by the data length belong to the data buffers. Note that all data
68/// buffers, except perhaps the last, contribute all their bytes to the
69/// `bdlbb::Blob` data. The last data buffer contributes anywhere between one
70/// and all of its bytes to the `bdlbb::Blob` data. The number of data buffers
71/// (returned by the `numDataBuffers` method), as well as the last data buffer
72/// length (returned by `lastDataBufferLength`), are maintained by `bdlbb::Blob`
73/// automatically when setting the length to a new value.
74///
75/// Buffers which do not contain data are referred to as capacity buffers. The
76/// total size of a blob does not decrease when setting the length to a value
77/// smaller than the current length. Instead, any data buffer that no longer
78/// contains data after the call to `setLength` becomes a capacity buffer, and
79/// may become a data buffer again later if setting length past its prefix size.
80///
81/// This design is intended to allow very efficient re-assignment of buffers (or
82/// part of buffers using shared pointer aliasing) between different blobs,
83/// without copying of the underlying data, while promoting efficient allocation
84/// of resources (via retaining capacity). Thus, `bdlbb::Blob` is an
85/// advantageous replacement for `bdlbb::PooledBufferChain` when manipulation of
86/// the sequence, sharing of portions of the sequence, and lifetime management
87/// of individual portions of the sequence, are desired. Another added
88/// flexibility of `bdlbb::Blob` is the possibility for buffers in the sequence
89/// to have different sizes (as opposed to a uniform fixed size for
90/// `bdlbb::PooledBufferChain`). When choosing whether to use a `bdlbb::Blob`
91/// vs. a `bdlbb::PooledBufferChain`, one must consider the added flexibility
92/// versus the added cost of shared ownership for each individual buffer and
93/// random access to the buffer.
94///
95/// ## Thread Safety {#bdlbb_blob-thread-safety}
96///
97///
98/// Different instances of the classes defined in this component can be
99/// concurrently modified by different threads. Thread safety of a particular
100/// instance is not guaranteed, and therefore must be handled by the user.
101///
102/// ## Usage {#bdlbb_blob-usage}
103///
104///
105/// This section illustrates intended use of this component.
106///
107/// ### Example 1: A Simple Blob Buffer Factory {#bdlbb_blob-example-1-a-simple-blob-buffer-factory}
108///
109///
110/// Classes that implement the `bdlbb::BlobBufferFactory` protocol are used to
111/// allocate `bdlbb::BlobBuffer` objects. A simple implementation follows:
112/// @code
113/// /// This factory creates blob buffers of a fixed size specified at
114/// /// construction.
115/// class SimpleBlobBufferFactory : public bdlbb::BlobBufferFactory {
116///
117/// // DATA
118/// bsl::size_t d_bufferSize;
119/// bslma::Allocator *d_allocator_p;
120///
121/// private:
122/// // Not implemented:
123/// SimpleBlobBufferFactory(const SimpleBlobBufferFactory&);
124/// SimpleBlobBufferFactory& operator=(const SimpleBlobBufferFactory&);
125///
126/// public:
127/// // CREATORS
128/// explicit SimpleBlobBufferFactory(int bufferSize = 1024,
129/// bslma::Allocator *basicAllocator = 0);
130/// ~SimpleBlobBufferFactory();
131///
132/// // MANIPULATORS
133/// void allocate(bdlbb::BlobBuffer *buffer);
134/// };
135///
136/// SimpleBlobBufferFactory::SimpleBlobBufferFactory(
137/// int bufferSize,
138/// bslma::Allocator *basicAllocator)
139/// : d_bufferSize(bufferSize)
140/// , d_allocator_p(bslma::Default::allocator(basicAllocator))
141/// {
142/// }
143///
144/// SimpleBlobBufferFactory::~SimpleBlobBufferFactory()
145/// {
146/// }
147///
148/// void SimpleBlobBufferFactory::allocate(bdlbb::BlobBuffer *buffer)
149/// {
150/// bsl::shared_ptr<char> shptr(
151/// (char *) d_allocator_p->allocate(d_bufferSize),
152/// d_allocator_p);
153///
154/// buffer->reset(shptr, d_bufferSize);
155/// }
156/// @endcode
157/// Note that should the user desire a blob buffer factory for his/her
158/// application, a better implementation that pools buffers is available in the
159/// @ref bdlbb_pooledblobbufferfactory component.
160///
161/// ### Simple Blob Usage {#bdlbb_blob-simple-blob-usage}
162///
163///
164/// Blobs can be created just by passing a factory that is responsible to
165/// allocate the `bdlbb::BlobBuffer`. The following simple program illustrates
166/// how.
167/// @code
168/// {
169/// SimpleBlobBufferFactory myFactory(1024);
170///
171/// bdlbb::Blob blob(&myFactory);
172/// assert(0 == blob.length());
173/// assert(0 == blob.totalSize());
174///
175/// blob.setLength(512);
176/// assert( 512 == blob.length());
177/// assert(1024 == blob.totalSize());
178/// @endcode
179/// Users need to access buffers directly in order to read/write data.
180/// @code
181/// char data[] = "12345678901234567890"; // 20 bytes
182/// assert(0 != blob.numBuffers());
183/// assert(static_cast<int>(sizeof(data)) <= blob.buffer(0).size());
184/// bsl::memcpy(blob.buffer(0).data(), data, sizeof(data));
185///
186/// blob.setLength(sizeof(data));
187/// assert(sizeof data == blob.length());
188/// assert( 1024 == blob.totalSize());
189/// @endcode
190/// A `bdlbb::BlobBuffer` can easily be re-assigned from one blob to another
191/// with no copy. In that case, the memory held by the buffer will be returned
192/// to its factory when the last blob referencing the buffer is destroyed. For
193/// the following example, a blob will be created using the default constructor.
194/// In this case, the `bdlbb::Blob` object will not able to grow on its own.
195/// Calling `setLength` for a number equal or greater than `totalSize()` will
196/// result in undefined behavior.
197/// @code
198/// bdlbb::Blob dest;
199/// assert( 0 == dest.length());
200/// assert( 0 == dest.totalSize());
201///
202/// assert(0 != blob.numBuffers());
203/// dest.appendBuffer(blob.buffer(0));
204/// assert( 0 == dest.length());
205/// assert(1024 == dest.totalSize());
206/// @endcode
207/// Note that at this point, the logical length (returned by `length`) of this
208/// object has not changed. `setLength` must be called explicitly by the user
209/// if the logical length of the `bdlbb::Blob` must be changed:
210/// @code
211/// dest.setLength(dest.buffer(0).size());
212/// assert(1024 == dest.length());
213/// assert(1024 == dest.totalSize());
214/// @endcode
215/// Sharing only a part of a buffer is also possible through shared pointer
216/// aliasing. In the following example, a buffer that contains only bytes 11-16
217/// from the first buffer of `blob` will be appended to `blob`.
218/// @code
219/// assert(0 != blob.numBuffers());
220/// assert(16 <= blob.buffer(0).size());
221///
222/// bsl::shared_ptr<char> shptr(blob.buffer(0).buffer(),
223/// blob.buffer(0).data() + 10);
224/// // 'shptr' is now an alias of 'blob.buffer(0).buffer()'.
225///
226/// bdlbb::BlobBuffer partialBuffer(shptr, 6);
227/// dest.appendBuffer(partialBuffer);
228/// // The last buffer of 'dest' contains only bytes 11-16 from
229/// // 'blob.buffer(0)'.
230/// }
231/// @endcode
232///
233/// ### Example 2: Data-Oriented Manipulation of a Blob {#bdlbb_blob-example-2-data-oriented-manipulation-of-a-blob}
234///
235///
236/// There are several typical ways of manipulating a blob: the simplest lets the
237/// blob automatically manage the length, by using only `prependBuffer`,
238/// `appendBuffer`, and `insertBuffer`. Consider the following typical
239/// utilities (these utilities are to illustrate usage, they are not meant to be
240/// copy-pasted into application programs although they can provide a foundation
241/// for application utilities):
242/// @code
243/// /// Prepend the specified `prolog` of the specified `length` to the
244/// /// specified `blob`, using the optionally specified `allocator` to
245/// /// supply any memory (or the currently installed default allocator if
246/// /// `allocator` is 0). The behavior is undefined unless
247/// /// `blob->totalSize() <= INT_MAX - length - sizeof(int)` and
248/// /// `blob->numBuffers() < INT_MAX`.
249/// void prependProlog(bdlbb::Blob *blob,
250/// const char *prolog,
251/// int length,
252/// bslma::Allocator *allocator = 0);
253///
254/// /// Load into the specified `blob` the data composed of the specified
255/// /// `prolog` and of the payload in the `numVectors` buffers pointed to
256/// /// by the specified `vectors` of the respective `vectorSizes`.
257/// /// Ownership of the vectors is transferred to the `blob` which will use
258/// /// the specified `deleter` to destroy them. Use the optionally
259/// /// specified `allocator` to supply memory, or the currently installed
260/// /// default allocator if `allocator` is 0. Note that any buffer
261/// /// belonging to `blob` prior to composing the message is not longer in
262/// /// `blob` after composing the message. Note also that `blob` need not
263/// /// have been created with a blob buffer factory. The behavior is
264/// /// undefined unless `blob` points to an initialized `bdlbb::Blob`
265/// /// instance.
266/// template <class DELETER>
267/// void composeMessage(bdlbb::Blob *blob,
268/// const bsl::string& prolog,
269/// char * const *vectors,
270/// const int *vectorSizes,
271/// int numVectors,
272/// const DELETER& deleter,
273/// bslma::Allocator *allocator = 0);
274///
275/// /// Insert a timestamp data buffer immediately after the prolog buffer
276/// /// and prior to any payload buffer. Return the number of bytes
277/// /// inserted. Use the optionally specified `allocator` to supply
278/// /// memory, or the currently installed default allocator if `allocator`
279/// /// is 0. The behavior is undefined unless the specified `blob` points
280/// /// to an initialized `bdlbb::Blob` instance with at least one data
281/// /// buffer.
282/// int timestampMessage(bdlbb::Blob *blob, bslma::Allocator *allocator = 0);
283/// @endcode
284/// A possible implementation using only `prependBuffer`, `appendBuffer`, and
285/// `insertBuffer` could be as follows:
286/// @code
287/// void prependProlog(bdlbb::Blob *blob,
288/// const char *prolog,
289/// int length,
290/// bslma::Allocator *allocator)
291/// {
292/// assert(blob);
293/// assert(blob->totalSize() <=
294/// INT_MAX - length - static_cast<int>(sizeof(int)));
295/// assert(blob->numBuffers() < INT_MAX);
296///
297/// (void)allocator;
298///
299/// int prologBufferSize =
300/// static_cast<int>(length + sizeof(int));
301/// SimpleBlobBufferFactory fa(prologBufferSize);
302/// bdlbb::BlobBuffer prologBuffer;
303/// fa.allocate(&prologBuffer);
304///
305/// bslx::MarshallingUtil::putInt32(prologBuffer.data(), length);
306/// bsl::memcpy(prologBuffer.data() + sizeof(int),
307/// prolog,
308/// length);
309/// assert(prologBuffer.size() == prologBufferSize);
310///
311/// blob->prependDataBuffer(prologBuffer);
312/// }
313/// @endcode
314/// Note that the length of `blob` in the above implementation is automatically
315/// incremented by `prologBuffer.size()`. Consider instead:
316/// @code
317/// blob->insertBuffer(0, prologBuffer);
318/// @endcode
319/// which inserts the prologBuffer before the first buffer of `blob`. This call
320/// will almost always adjust the length properly *except* if the length of
321/// `blob` is 0 before the insertion (i.e., the message has an empty payload).
322/// In that case, the resulting `blob` will still be empty after
323/// `prependProlog`, which, depending on the intention of the programmer, could
324/// be intended (avoid sending empty messages) or could be (most likely) a
325/// mistake.
326///
327/// The `composeMessage` implementation is simplified by using `prependProlog`:
328/// @code
329/// template <class DELETER>
330/// void composeMessage(bdlbb::Blob *blob,
331/// const char *prolog,
332/// int prologLength,
333/// char * const *vectors,
334/// const int *vectorSizes,
335/// int numVectors,
336/// const DELETER& deleter,
337/// bslma::Allocator *allocator)
338/// {
339/// assert(blob);
340/// assert(vectors);
341/// assert(0 <= numVectors);
342///
343/// blob->removeAll();
344/// prependProlog(blob, prolog, prologLength, allocator);
345///
346/// for (int i = 0; i < numVectors; ++i) {
347/// bsl::shared_ptr<char> shptr(vectors[i], deleter, allocator);
348/// bdlbb::BlobBuffer partialBuffer(shptr, vectorSizes[i]);
349/// blob->appendDataBuffer(partialBuffer);
350/// // The last buffer of 'dest' contains only bytes 11-16 from
351/// // 'blob.buffer(0)'.
352/// }
353/// }
354/// @endcode
355/// Note that the `deleter` is used to destroy the buffers transferred by
356/// `vectors`, but not the prolog buffer.
357///
358/// Timestamping a message is done by creating a buffer holding a timestamp, and
359/// inserting it after the prolog and before the payload of the message. Note
360/// that in typical messages, timestamps would be part of the prolog itself, so
361/// this is a somewhat contrived example for exposition only.
362/// @code
363/// int timestampMessage(bdlbb::Blob *blob, bslma::Allocator *allocator)
364/// {
365/// assert(blob);
366/// assert(0 < blob->numDataBuffers());
367///
368/// bdlbb::BlobBuffer buffer;
369/// bdlt::Datetime now = bdlt::CurrentTime::utc();
370///
371/// SimpleBlobBufferFactory fa(128, allocator);
372/// bdlbb::BlobBuffer timestampBuffer;
373/// fa.allocate(&timestampBuffer);
374///
375/// bslx::ByteOutStream bdexStream(20150826);
376/// now.bdexStreamOut(bdexStream, 1);
377/// assert(bdexStream);
378/// assert(bdexStream.length() < 128);
379/// bsl::memcpy(timestampBuffer.data(),
380/// bdexStream.data(),
381/// bdexStream.length());
382/// timestampBuffer.setSize(static_cast<int>(bdexStream.length()));
383/// @endcode
384/// Now that we have fabricated the buffer holding the current data and time, we
385/// must insert it into the blob after the first buffer (i.e., before the buffer
386/// at index 1). Note however that the payload could be empty, a condition
387/// tested by the fact that there is only one data buffer in `blob`. In that
388/// case, it would be a mistake to use `insertBuffer` since it would not modify
389/// the length of the blob.
390/// @code
391/// if (1 < blob->numDataBuffers()) {
392/// blob->insertBuffer(1, timestampBuffer);
393/// } else {
394/// blob->appendDataBuffer(timestampBuffer);
395/// }
396///
397/// return static_cast<int>(bdexStream.length());
398/// }
399/// @endcode
400/// Note that the call to `appendDataBuffer` also takes care of the possibility
401/// that the first buffer of `blob` may not be full to capacity (if the length
402/// of the blob was smaller than the buffer size, only the first
403/// `blob->length()` bytes would contain prolog data). In that case, that
404/// buffer is trimmed before appending the `timestampBuffer` so that the first
405/// byte of the `timestampBuffer` appears immediately next to the last prolog
406/// byte, and the blob length is automatically incremented by the size of the
407/// `timestampBuffer`.
408/// @}
409/** @} */
410/** @} */
411
412/** @addtogroup bdl
413 * @{
414 */
415/** @addtogroup bdlbb
416 * @{
417 */
418/** @addtogroup bdlbb_blob
419 * @{
420 */
421
422#include <bdlscm_version.h>
423
424#include <bslma_allocator.h>
425
427#include <bslmf_movableref.h>
428
429#include <bsls_assert.h>
430#include <bsls_keyword.h>
431#include <bsls_review.h>
432
433#include <bsl_iosfwd.h>
434#include <bsl_memory.h>
435#include <bsl_vector.h>
436
437#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
438#include <bslalg_typetraits.h>
439#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
440
441
442namespace bdlbb {
443
444 // ================
445 // class BlobBuffer
446 // ================
447
448/// `BlobBuffer` is a simple in-core representation of a shared buffer.
449/// This class is exception-neutral with no guarantee of rollback: if an
450/// exception is thrown during the invocation of a method on a pre-existing
451/// instance, the container is left in a valid state, but its value is
452/// undefined. In no event is memory leaked.
453///
454/// See @ref bdlbb_blob
456
457 // PRIVATE TYPES
458
459 /// Used in move construction and assignment to make lines shorter.
461
462 // DATA
463 bsl::shared_ptr<char> d_buffer; // shared buffer
464 int d_size; // buffer size (in bytes)
465
466 // FRIENDS
467 friend bool operator==(const BlobBuffer&, const BlobBuffer&);
468
469 friend bool operator!=(const BlobBuffer&, const BlobBuffer&);
470
471 public:
472 // CREATORS
473
474 /// Create a blob buffer representing a null buffer. Note that the
475 /// `size` and `data` methods of a default-constructed blob buffer both
476 /// return 0.
477 BlobBuffer();
478
479 /// Create a blob buffer representing the specified `buffer` of the
480 /// specified `size`. The behavior is undefined unless `0 <= size` and
481 /// the `buffer` refers to a continuous block of memory of at least
482 /// `size` bytes.
484
485 /// Create a blob buffer representing the specified moveable `buffer` of
486 /// the specified `size`. The behavior is undefined unless `0 <= size`
487 /// and the `buffer` refers to a continuous block of memory of at least
488 /// `size` bytes.
490
491 /// Create a blob buffer having the same value as the specified
492 /// `original` blob buffer.
493 BlobBuffer(const BlobBuffer& original);
494
495 /// Create a blob buffer object having the same value as the specified
496 /// `original` object by moving the contents of `original` to the
497 /// newly-created object. `original` is left in a valid but unspecified
498 /// state.
500
501 /// Destroy this blob buffer.
502 ~BlobBuffer();
503
504 // MANIPULATORS
505
506 /// Assign to this blob buffer the value of the specified `rhs` blob
507 /// buffer, and return a reference to this modifiable blob buffer.
509
510 /// Assign to this object the value of the specified `rhs`, and return a
511 /// reference providing modifiable access to this object. The contents
512 /// of `rhs` are move-assigned to this object. `rhs` is left in a valid
513 /// but unspecified state.
515
516 /// Reset this blob buffer to its default-constructed state.
517 void reset();
518
519 /// Set the buffer represented by this object to the specified `buffer`
520 /// of the specified `size`. The behavior is undefined unless
521 /// `0 <= size` and the `buffer` refers to a continuous block of memory
522 /// of at least `size` bytes.
524
525 /// Set the buffer represented by this object to the specified moveable
526 /// `buffer` of the specified `size`. The behavior is undefined unless
527 /// `0 <= size` and the `buffer` refers to a continuous block of memory
528 /// of at least `size` bytes.
530
531 /// Return a reference to the shared pointer to the modifiable buffer
532 /// represented by this object.
534
535 /// Set the size of this blob buffer to the specified `size`. The
536 /// behavior is undefined unless `0 <= size` and the capacity of the
537 /// buffer returned by the `buffer` method is at least `size` bytes.
538 void setSize(int size);
539
540 /// Efficiently exchange the value of this object with the value of the
541 /// specified `other` object. This method provides the no-throw
542 /// exception-safety guarantee.
543 void swap(BlobBuffer& other);
544
545 /// Reduce this buffer to the specified `toSize` and return the
546 /// leftover. The behaviour is undefined unless '0 <= toSize && toSize
547 /// <= size()'.
548 BlobBuffer trim(int toSize);
549
550 // ACCESSORS
551
552 /// Return a reference to the non-modifiable shared pointer to the
553 /// buffer represented by this object.
554 const bsl::shared_ptr<char>& buffer() const;
555
556 /// Return the address of the modifiable buffer represented by this
557 /// object.
558 char *data() const;
559
560 /// Return the size of the buffer represented by this object.
561 int size() const;
562
563 /// Format this object as a hexadecimal dump on the specified `stream`,
564 /// and return a reference to the modifiable `stream`. Note that the
565 /// optionally specified `level` and `spacesPerLevel` arguments are
566 /// specified for interface compatibility only and are effectively
567 /// ignored.
568 bsl::ostream& print(bsl::ostream& stream,
569 int level = 0,
570 int spacesPerLevel = 4) const;
571};
572} // close package namespace
573
574// TYPE TRAITS
575
576namespace bslmf {
577
578template <>
580: IsBitwiseMoveable<bsl::shared_ptr<char> >::type {
581};
582
583} // close namespace bslmf
584
585namespace bdlbb {
586
587// FREE OPERATORS
588
589/// Return `true` if the specified `lhs` and `rhs` blob buffers have the
590/// same value, and `false` otherwise. Two blob buffers have the same value
591/// if they represent the same buffer of the same size.
592bool operator==(const BlobBuffer& lhs, const BlobBuffer& rhs);
593
594/// Return `true` if the specified `lhs` and `rhs` blob buffers do not have
595/// the same value, and `false` otherwise. Two blob buffers do not have the
596/// same value if they do not represent the same buffer of the same size.
597bool operator!=(const BlobBuffer& lhs, const BlobBuffer& rhs);
598
599/// Format the specified blob `buffer` to the specified output `stream`, and
600/// return a reference to the modifiable `stream`.
601bsl::ostream& operator<<(bsl::ostream& stream, const BlobBuffer& buffer);
602
603// FREE FUNCTIONS
604
605/// Efficiently exchange the values of the specified `a` and `b` objects.
606/// This method provides the no-throw exception-safety guarantee.
607void swap(BlobBuffer& a, BlobBuffer& b);
608
609 // =======================
610 // class BlobBufferFactory
611 // =======================
612
613/// This class defines a base-level protocol for a `BlobBuffer` factory.
614///
615/// See @ref bdlbb_blob
617
618 public:
619 // CREATORS
620
621 /// Destroy this blob buffer factory.
623
624 // MANIPULATORS
625
626 /// Allocate a blob buffer from this blob buffer factory, and load it
627 /// into the specified `buffer`.
628 virtual void allocate(BlobBuffer *buffer) = 0;
629};
630
631 // ==========
632 // class Blob
633 // ==========
634
635/// `Blob` is an in-core container for `BlobBuffer` objects. This class is
636/// exception-neutral with no guarantee of rollback: if an exception is
637/// thrown during the invocation of a method on a pre-existing instance, the
638/// container is left in a valid state, but its value is undefined. In no
639/// event is memory leaked.
640///
641/// See @ref bdlbb_blob
642class Blob {
643
644 // PRIVATE TYPES
645
646 /// Used in move construction and assignment to make lines shorter.
648
649 // DATA
650 bsl::vector<BlobBuffer> d_buffers; // buffer sequence
651
652 int d_totalSize; // capacity of blob (in
653 // bytes)
654
655 int d_dataLength; // length (in bytes) of
656 // user-managed data
657
658 int d_dataIndex; // index of the last data
659 // buffer, or -1 if the
660 // blob has no data buffers
661
662 int d_preDataIndexLength; // sum of the lengths of
663 // all data buffers,
664 // excluding the last one
665
666 BlobBufferFactory *d_bufferFactory_p; // factory used to grow
667 // blob (held)
668
669 // FRIENDS
670 friend bool operator==(const Blob&, const Blob&);
671 friend bool operator!=(const Blob&, const Blob&);
672
673 private:
674 // PRIVATE MANIPULATORS
675
676 /// Set the length of this blob to the specified `length` and, if
677 /// `length` is greater than its total size, grow this blob by appending
678 /// buffers allocated using this object's underlying
679 /// `BlobBufferFactory`. This function implements the "slow-path" for
680 /// `setLength`, handling the cases where the supplied `length` is lies
681 /// beyond the boundaries of the last data buffer. The behavior is
682 /// undefined if `length` is a negative value, if the new length
683 /// requires growing the blob and this blob has no underlying factory,
684 /// or if the `length` lies within the boundaries of the last data
685 /// buffer.
686 void slowSetLength(int length);
687
688 // PRIVATE ACCESSORS
689
690 /// Assert the invariants of this object and return 0 on success.
691 int assertInvariants() const;
692
693 public:
694 // CREATORS
695
696 /// Create an empty blob having no factory to allocate blob buffers.
697 /// Since there is no factory, the behavior is undefined if the length
698 /// of the blob is set beyond the total size. Optionally specify a
699 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
700 /// the currently installed default allocator is used.
701 explicit Blob(bslma::Allocator *basicAllocator = 0);
702
703 /// Create an empty blob using the specified `factory` to allocate blob
704 /// buffers. Optionally specify a `basicAllocator` used to supply
705 /// memory. If `basicAllocator` is 0, the currently installed default
706 /// allocator is used.
708 bslma::Allocator *basicAllocator = 0);
709
710 /// Create a blob that initially holds the specified `numBuffers`
711 /// buffers referenced by the specified `buffers`, and uses the
712 /// specified `factory` to allocate blob buffers. Optionally specify a
713 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
714 /// the currently installed default allocator is used.
715 Blob(const BlobBuffer *buffers,
716 int numBuffers,
718 bslma::Allocator *basicAllocator = 0);
719
720 /// Create a blob that holds the same buffers as the specified
721 /// `original` blob, and uses the specified `factory` to allocate blob
722 /// buffers. Optionally specify a `basicAllocator` used to supply
723 /// memory. If `basicAllocator` is 0, the currently installed default
724 /// allocator is used.
725 Blob(const Blob& original,
727 bslma::Allocator *basicAllocator = 0);
728
729 /// Create a blob that holds the same buffers as the specified
730 /// `original` blob, and has no factory to allocate blob buffers. Since
731 /// there is no factory, the behavior is undefined if the length of the
732 /// blob is set beyond the total size. Optionally specify a
733 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
734 /// the currently installed default allocator is used.
735 Blob(const Blob& original, bslma::Allocator *basicAllocator = 0);
736
737 /// Create a blob object having the same value as the specified
738 /// `original` object by moving the contents of `original` to the
739 /// newly-created object. The allocator associated with `original` is
740 /// propagated for use in the newly-created object. `original` is left
741 /// in a valid but unspecified state.
743
744 /// Create a blob object having the same value as the specified
745 /// `original` object that uses the specified `basicAllocator` to supply
746 /// memory. If `basicAllocator` is 0, the currently installed default
747 /// allocator is used. The contents of `original` are moved to the
748 /// newly-created object. `original` is left in a valid but unspecified
749 /// state.
751 bslma::Allocator *basicAllocator);
752
753 /// Destroy this blob.
755
756 // MANIPULATORS
757
758 /// Assign to this blob the value of the specified `rhs` blob, and
759 /// return a reference to this modifiable blob.
760 Blob& operator=(const Blob& rhs);
761
762 /// Assign to this object the value of the specified `rhs`, and return a
763 /// reference providing modifiable access to this object. The contents
764 /// of `rhs` are move-assigned to this object. `rhs` is left in a valid
765 /// but unspecified state.
767
768 /// Append the specified `buffer` after the last buffer of this blob.
769 /// The length of this blob is unaffected. The behavior is undefined
770 /// unless neither the total size of the resulting blob nor its total
771 /// number of buffers exceeds `INT_MAX`. Note that this operation is
772 /// equivalent to `insertBuffer(numBuffers(), buffer)`, but is more
773 /// efficient.
774 void appendBuffer(const BlobBuffer& buffer);
775
776 /// Append the specified move-insertable `buffer` after the last buffer
777 /// of this blob. The `buffer` is left in a valid but unspecified
778 /// state. The length of this blob is unaffected. The behavior is
779 /// undefined unless neither the total size of the resulting blob nor
780 /// its total number of buffers exceeds `INT_MAX`. Note that this
781 /// operation is equivalent to `insertBuffer(numBuffers(), buffer)`, but
782 /// is more efficient.
784
785 /// Append the specified `buffer` after the last *data* buffer of this
786 /// blob; the last data buffer is trimmed, if necessary. The length of
787 /// this blob is incremented by the size of `buffer`. The behavior is
788 /// undefined unless neither the total size of the resulting blob nor
789 /// its total number of buffers exceeds `INT_MAX`. Note that this
790 /// operation is equivalent to:
791 /// @code
792 /// const int n = blob.length();
793 /// blob.trimLastDataBuffer();
794 /// blob.insertBuffer(numDataBuffers(), buffer);
795 /// blob.setLength(n + buffer.size());
796 /// @endcode
797 /// but is more efficient.
799
800 /// Append the specified move-insertable `buffer` after the last *data*
801 /// buffer of this blob; the last data buffer is trimmed, if necessary.
802 /// The `buffer` is left in a valid but unspecified state. The length
803 /// of this blob is incremented by the size of `buffer`. The behavior
804 /// is undefined unless neither the total size of the resulting blob nor
805 /// its total number of buffers exceeds `INT_MAX`. Note that this
806 /// operation is equivalent to:
807 /// @code
808 /// const int n = blob.length();
809 /// blob.trimLastDataBuffer();
810 /// blob.insertBuffer(numDataBuffers(), MoveUtil::move(buffer));
811 /// blob.setLength(n + buffer.size());
812 /// @endcode
813 /// but is more efficient.
815
816 /// Insert the specified `buffer` at the specified `index` in this blob.
817 /// Increment the length of this blob by the size of `buffer` if
818 /// `buffer` is inserted *before* the logical end of this blob. The
819 /// length of this blob is <u>unchanged</u> if inserting at a position
820 /// following all data buffers (e.g., inserting into an empty blob or
821 /// inserting a buffer to increase capacity); in that case, the blob
822 /// length must be changed by an explicit call to `setLength`. Buffers
823 /// at `index` and higher positions (if any) are shifted up by one index
824 /// position. The behavior is undefined unless
825 /// `0 <= index <= numBuffers()` and neither the total size of the
826 /// resulting blob nor its total number of buffers exceeds `INT_MAX`.
827 void insertBuffer(int index, const BlobBuffer& buffer);
828
829 /// Insert the specified move-insertable `buffer` at the specified
830 /// `index` in this blob. Increment the length of this blob by the size
831 /// of `buffer` if `buffer` is inserted *before* the logical end of this
832 /// blob. The length of this blob is <u>unchanged</u> if inserting at a
833 /// position following all data buffers (e.g., inserting into an empty
834 /// blob or inserting a buffer to increase capacity); in that case, the
835 /// blob length must be changed by an explicit call to `setLength`.
836 /// Buffers at `index` and higher positions (if any) are shifted up by
837 /// one index position. The `buffer` is left in a valid but unspecified
838 /// state. The behavior is undefined unless
839 /// `0 <= index <= numBuffers()` and neither the total size of the
840 /// resulting blob nor its total number of buffers exceeds `INT_MAX`.
842
843 /// Insert the specified `buffer` before the beginning of this blob.
844 /// The length of this blob is incremented by the length of the
845 /// prepended buffer. The behavior is undefined unless neither the
846 /// total size of the resulting blob nor its total number of buffers
847 /// exceeds `INT_MAX`. Note that this operation is equivalent to:
848 /// @code
849 /// const int n = blob.length();
850 /// blob.insertBuffer(0, buffer);
851 /// blob.setLength(n + buffer.size());
852 /// @endcode
853 /// but is more efficient.
855
856 /// Insert the specified move-insertable `buffer` before the beginning
857 /// of this blob. The length of this blob is incremented by the length
858 /// of the prepended buffer. The `buffer` is left in a valid but
859 /// unspecified state. The behavior is undefined unless neither the
860 /// total size of the resulting blob nor its total number of buffers
861 /// exceeds `INT_MAX`. Note that this operation is equivalent to:
862 /// @code
863 /// const int n = blob.length();
864 /// blob.insertBuffer(0, MoveUtil::move(buffer));
865 /// blob.setLength(n + buffer.size());
866 /// @endcode
867 /// but is more efficient.
869
870 /// Remove all blob buffers from this blob, and set its length to 0.
871 void removeAll();
872
873 /// Remove the buffer at the specified `index` from this blob, and
874 /// decrement the length of this blob by the size of `buffer` if the
875 /// buffer at `index` contains data bytes (i.e., if the first byte of
876 /// `buffer` occurs before the logical end of this blob). Buffers at
877 /// positions higher than `index` (if any) are shifted down by one index
878 /// position. The behavior is undefined unless
879 /// `0 <= index < numBuffers()`.
880 void removeBuffer(int index);
881
882 /// Remove the specified `numBuffers` starting at the specified `index`
883 /// from this blob. Buffers at positions higher than `index` (if any)
884 /// are shifted down by `numBuffers` index positions. The behavior is
885 /// undefined unless `0 <= index`, `0 <= numBuffers`, and
886 /// `index + numBuffers <= numBuffers()`.
887 void removeBuffers(int index, int numBuffers);
888
889 /// Remove any unused capacity buffers from this blob. Note that this
890 /// method does not trim the last data buffer, and that the resulting
891 /// `totalSize` will be `length` plus any unused capacity in the last
892 /// buffer having data.
894
895 /// Replace the data buffer at the specified `index` with the specified
896 /// `buffer`. The behavior is undefined unless
897 /// `0 <= index < numDataBuffers()` and the total size of the resulting
898 /// blob does not exceed `INT_MAX`. Note that this operation is
899 /// equivalent to:
900 /// @code
901 /// blob.removeBuffer(index);
902 /// const int n = blob.length();
903 /// blob.insertBuffer(index, buffer);
904 /// blob.setLength(n + buffer.size());
905 /// @endcode
906 /// but is more efficient.
907 void replaceDataBuffer(int index, const BlobBuffer& buffer);
908
909 /// Allocate sufficient capacity to store at least the specified
910 /// `numBuffers` buffers. The behavior is undefined unless
911 /// `0 <= numBuffers`. Note that this method does not change the length
912 /// of this blob or add any buffers to it. Note also that the internal
913 /// capacity will be increased to maintain a geometric growth factor.
915
916 /// Set the length of this blob to the specified `length` and, if
917 /// `length` is greater than its total size, grow this blob by appending
918 /// buffers allocated using this object's underlying
919 /// `BlobBufferFactory`. The behavior is undefined if `length` is a
920 /// negative value, or if the new length requires growing the blob and
921 /// this blob has no underlying factory.
922 void setLength(int length);
923
924 /// Efficiently exchange the value of this object with the value of the
925 /// specified `other` object. This method provides the no-throw
926 /// exception-safety guarantee. The behavior is undefined unless this
927 /// object was created with the same allocator as `other`.
928 void swap(Blob& other);
929
930 /// Swap the blob buffer at the specified `index` with the specified
931 /// `srcBuffer`. The behavior is undefined unless
932 /// `0 <= index < numBuffers()` and
933 /// `srcBuffer->size() == buffer(index).size()`. Note that other than
934 /// the buffer swap the state of this object remains unchanged.
935 void swapBufferRaw(int index, BlobBuffer *srcBuffer);
936
937 /// Set the size of the last data buffer to `lastDataBufferLength()`.
938 /// If there are no data buffers, or if the last data buffer is full
939 /// (i.e., its size is `lastDataBufferLength()`), then this method has
940 /// no effect. Return the leftover of the trimmed buffer or default
941 /// constructed `BlobBuffer` if nothing to trim. Note that the length
942 /// of the blob is unchanged, and that capacity buffers (i.e., of
943 /// indices `numDataBuffers()` and higher) are *not* removed.
945
946 /// Remove all blob buffers from this blob and move the buffers held by
947 /// the specified `srcBlob` to this blob. Note that this method is
948 /// logically equivalent to:
949 /// @code
950 /// *this = *srcBlob;
951 /// srcBlob->removeAll();
952 /// @endcode
953 /// but its implementation is more efficient.
954 void moveBuffers(Blob *srcBlob);
955
956 /// Remove all blob buffers from this blob and move the data buffers
957 /// held by the specified `srcBlob` to this blob.
958 void moveDataBuffers(Blob *srcBlob);
959
960 /// Move the data buffers held by the specified `srcBlob` to this blob
961 /// appending them to the current data buffers of this blob. The
962 /// behavior is undefined unless the total size of the resulting blob
963 /// and the total number of buffers in this blob are less than or
964 /// equal to `INT_MAX`.
966
967 // ACCESSORS
968
969 /// Return the allocator used by this object to supply memory.
971
972 /// Return a reference to the non-modifiable blob buffer at the
973 /// specified `index` in this blob. The behavior is undefined unless
974 /// `0 <= index < numBuffers()`.
975 const BlobBuffer& buffer(int index) const;
976
977 /// Return the factory used by this object.
978 BlobBufferFactory *factory() const;
979
980 /// Return the length of the last blob buffer in this blob, or 0 if this
981 /// blob is of 0 length.
982 int lastDataBufferLength() const;
983
984 /// Return the length of this blob.
985 int length() const;
986
987 /// Return the number of blob buffers containing data in this blob.
988 int numDataBuffers() const;
989
990 /// Return the number of blob buffers held by this blob.
991 int numBuffers() const;
992
993 /// Return the sum of the sizes of all blob buffers in this blob (i.e.,
994 /// the capacity of this blob).
995 int totalSize() const;
996};
997} // close package namespace
998
999// TYPE TRAITS
1000
1001namespace bslmf {
1002
1003template <>
1004struct IsBitwiseMoveable<BloombergLP::bdlbb::Blob>
1005: IsBitwiseMoveable<bsl::vector<BloombergLP::bdlbb::BlobBuffer> >::type {
1006};
1007} // close namespace bslmf
1008
1009namespace bslma {
1010
1011template <>
1013};
1014} // close namespace bslma
1015
1016namespace bdlbb {
1017
1018// FREE OPERATORS
1019
1020/// Return `true` if the specified `lhs` and `rhs` blobs have the same
1021/// value, and `false` otherwise. Two blobs have the same value if they
1022/// hold the same buffers, and have the same length.
1023bool operator==(const Blob& lhs, const Blob& rhs);
1024
1025/// Return `true` if the specified `lhs` and `rhs` blobs do not have the
1026/// same value, and `false` otherwise. Two blobs do not have the same value
1027/// if they do not hold the same buffers, or do not have the same length.
1028bool operator!=(const Blob& lhs, const Blob& rhs);
1029
1030// FREE FUNCTIONS
1031
1032/// Efficiently exchange the values of the specified `a` and `b` objects.
1033/// This method provides the no-throw exception-safety guarantee if both
1034/// objects were created with the same allocator.
1035void swap(Blob& a, Blob& b);
1036
1037// ============================================================================
1038// INLINE DEFINITIONS
1039// ============================================================================
1040
1041 // ----------------
1042 // class BlobBuffer
1043 // ----------------
1044
1045// CREATORS
1046inline
1048: d_size(0)
1049{
1050}
1051
1052inline
1054: d_buffer(buffer)
1055, d_size(size)
1056{
1057 BSLS_ASSERT(0 <= size);
1058 BSLS_ASSERT(size == 0 || buffer);
1059}
1060
1061inline
1063 int size)
1064: d_buffer(MoveUtil::move(buffer))
1065, d_size(size)
1066{
1067 BSLS_ASSERT(0 <= size);
1068 BSLS_ASSERT(size == 0 || d_buffer);
1069}
1070
1071inline
1073: d_buffer(original.d_buffer)
1074, d_size(original.d_size)
1075{
1076}
1077
1078inline
1081: d_buffer(MoveUtil::move(MoveUtil::access(original).d_buffer))
1082, d_size(MoveUtil::move(MoveUtil::access(original).d_size))
1083{
1084 MoveUtil::access(original).d_size = 0;
1085}
1086
1087inline
1091
1092// MANIPULATORS
1093inline
1095{
1096 return d_buffer;
1097}
1098
1099inline
1101{
1102 BSLS_ASSERT(0 <= size);
1103
1104 d_size = size;
1105}
1106
1107// ACCESSORS
1108inline
1110{
1111 return d_buffer;
1112}
1113
1114inline
1115char *BlobBuffer::data() const
1116{
1117 return d_buffer.get();
1118}
1119
1120inline
1122{
1123 return d_size;
1124}
1125} // close package namespace
1126
1127// FREE OPERATORS
1128inline
1129bool bdlbb::operator==(const BlobBuffer& lhs, const BlobBuffer& rhs)
1130{
1131 return lhs.d_buffer.get() == rhs.d_buffer.get() &&
1132 lhs.d_size == rhs.d_size;
1133}
1134
1135inline
1136bool bdlbb::operator!=(const BlobBuffer& lhs, const BlobBuffer& rhs)
1137{
1138 return lhs.d_buffer.get() != rhs.d_buffer.get() ||
1139 lhs.d_size != rhs.d_size;
1140}
1141
1142namespace bdlbb {
1143
1144 // ----------
1145 // class Blob
1146 // ----------
1147
1148// MANIPULATORS
1149inline
1151{
1152 BlobBuffer objectToMove(buffer);
1153 appendBuffer(MoveUtil::move(objectToMove));
1154}
1155
1156inline
1158{
1159 BlobBuffer objectToMove(buffer);
1160 appendDataBuffer(MoveUtil::move(objectToMove));
1161}
1162
1163inline
1164void Blob::insertBuffer(int index, const BlobBuffer& buffer)
1165{
1166 BlobBuffer objectToMove(buffer);
1167 insertBuffer(index, MoveUtil::move(objectToMove));
1168}
1169
1170inline
1172{
1173 BlobBuffer objectToMove(buffer);
1174 prependDataBuffer(MoveUtil::move(objectToMove));
1175}
1176
1177inline
1179{
1180 BSLS_ASSERT(0 <= numBuffers);
1181
1183 size_t newCapacity = static_cast<size_t>(numBuffers);
1184 if (newCapacity > d_buffers.capacity()) {
1185 size_t geometric = d_buffers.capacity() * 2;
1186 newCapacity = geometric > newCapacity ? geometric : newCapacity;
1187 d_buffers.reserve(newCapacity);
1188 }
1189}
1190
1191// ACCESSORS
1192inline
1194{
1195 return d_buffers.get_allocator().mechanism();
1196}
1197
1198inline
1199const BlobBuffer& Blob::buffer(int index) const
1200{
1201 BSLS_ASSERT_SAFE(0 <= index);
1202 BSLS_ASSERT_SAFE(index < static_cast<int>(d_buffers.size()));
1203
1204 return d_buffers[index];
1205}
1206
1207inline
1209{
1210 return d_bufferFactory_p;
1211}
1212
1213inline
1215{
1216 return d_dataLength - d_preDataIndexLength;
1217}
1218
1219inline
1220int Blob::length() const
1221{
1222 return d_dataLength;
1223}
1224
1225inline
1227{
1228 return static_cast<int>(d_buffers.size());
1229}
1230
1231inline
1233{
1234 return d_dataIndex + 1;
1235}
1236
1237inline
1239{
1240 return d_totalSize;
1241}
1242
1243} // close package namespace
1244
1245
1246
1247#endif
1248
1249// ----------------------------------------------------------------------------
1250// Copyright 2018 Bloomberg Finance L.P.
1251//
1252// Licensed under the Apache License, Version 2.0 (the "License");
1253// you may not use this file except in compliance with the License.
1254// You may obtain a copy of the License at
1255//
1256// http://www.apache.org/licenses/LICENSE-2.0
1257//
1258// Unless required by applicable law or agreed to in writing, software
1259// distributed under the License is distributed on an "AS IS" BASIS,
1260// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1261// See the License for the specific language governing permissions and
1262// limitations under the License.
1263// ----------------------------- END-OF-FILE ----------------------------------
1264
1265/** @} */
1266/** @} */
1267/** @} */
Definition bdlbb_blob.h:616
virtual ~BlobBufferFactory()
Destroy this blob buffer factory.
virtual void allocate(BlobBuffer *buffer)=0
Definition bdlbb_blob.h:455
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
BlobBuffer trim(int toSize)
void reset(bslmf::MovableRef< bsl::shared_ptr< char > > buffer, int size)
bsl::shared_ptr< char > & buffer()
Definition bdlbb_blob.h:1094
void reset(const bsl::shared_ptr< char > &buffer, int size)
void reset()
Reset this blob buffer to its default-constructed state.
friend bool operator!=(const BlobBuffer &, const BlobBuffer &)
~BlobBuffer()
Destroy this blob buffer.
Definition bdlbb_blob.h:1088
BlobBuffer()
Definition bdlbb_blob.h:1047
friend bool operator==(const BlobBuffer &, const BlobBuffer &)
BlobBuffer & operator=(const BlobBuffer &rhs)
char * data() const
Definition bdlbb_blob.h:1115
BlobBuffer & operator=(bslmf::MovableRef< BlobBuffer > rhs)
int size() const
Return the size of the buffer represented by this object.
Definition bdlbb_blob.h:1121
void setSize(int size)
Definition bdlbb_blob.h:1100
void swap(BlobBuffer &other)
Definition bdlbb_blob.h:642
void prependDataBuffer(const BlobBuffer &buffer)
Definition bdlbb_blob.h:1171
int lastDataBufferLength() const
Definition bdlbb_blob.h:1214
void removeAll()
Remove all blob buffers from this blob, and set its length to 0.
int length() const
Return the length of this blob.
Definition bdlbb_blob.h:1220
bslma::Allocator * allocator() const
Return the allocator used by this object to supply memory.
Definition bdlbb_blob.h:1193
int numDataBuffers() const
Return the number of blob buffers containing data in this blob.
Definition bdlbb_blob.h:1232
friend bool operator==(const Blob &, const Blob &)
void removeBuffer(int index)
Blob(BlobBufferFactory *factory, bslma::Allocator *basicAllocator=0)
Blob(bslma::Allocator *basicAllocator=0)
void insertBuffer(int index, bslmf::MovableRef< BlobBuffer > buffer)
const BlobBuffer & buffer(int index) const
Definition bdlbb_blob.h:1199
void appendDataBuffer(bslmf::MovableRef< BlobBuffer > buffer)
Blob(const BlobBuffer *buffers, int numBuffers, BlobBufferFactory *factory, bslma::Allocator *basicAllocator=0)
void moveAndAppendDataBuffers(Blob *srcBlob)
void appendBuffer(bslmf::MovableRef< BlobBuffer > buffer)
void insertBuffer(int index, const BlobBuffer &buffer)
Definition bdlbb_blob.h:1164
void moveBuffers(Blob *srcBlob)
Blob(bslmf::MovableRef< Blob > original) BSLS_KEYWORD_NOEXCEPT
int numBuffers() const
Return the number of blob buffers held by this blob.
Definition bdlbb_blob.h:1226
BlobBuffer trimLastDataBuffer()
Blob(const Blob &original, bslma::Allocator *basicAllocator=0)
void appendDataBuffer(const BlobBuffer &buffer)
Definition bdlbb_blob.h:1157
friend bool operator!=(const Blob &, const Blob &)
void appendBuffer(const BlobBuffer &buffer)
Definition bdlbb_blob.h:1150
Blob(bslmf::MovableRef< Blob > original, bslma::Allocator *basicAllocator)
Blob & operator=(bslmf::MovableRef< Blob > rhs)
void moveDataBuffers(Blob *srcBlob)
Blob & operator=(const Blob &rhs)
void prependDataBuffer(bslmf::MovableRef< BlobBuffer > buffer)
~Blob()
Destroy this blob.
Blob(const Blob &original, BlobBufferFactory *factory, bslma::Allocator *basicAllocator=0)
void removeUnusedBuffers()
int totalSize() const
Definition bdlbb_blob.h:1238
void setLength(int length)
void replaceDataBuffer(int index, const BlobBuffer &buffer)
BlobBufferFactory * factory() const
Return the factory used by this object.
Definition bdlbb_blob.h:1208
void reserveBufferCapacity(int numBuffers)
Definition bdlbb_blob.h:1178
void removeBuffers(int index, int numBuffers)
void swap(Blob &other)
void swapBufferRaw(int index, BlobBuffer *srcBuffer)
Definition bslstl_sharedptr.h:1830
element_type * get() const BSLS_KEYWORD_NOEXCEPT
Definition bslstl_sharedptr.h:5574
Definition bslstl_vector.h:1025
AllocatorTraits::size_type size_type
Definition bslstl_vector.h:1052
Definition bslma_allocator.h:457
Definition bslmf_movableref.h:751
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
#define BSLS_KEYWORD_NOEXCEPT
Definition bsls_keyword.h:632
Definition bdlbb_blob.h:442
bsl::ostream & operator<<(bsl::ostream &stream, const BlobBuffer &buffer)
bool operator!=(const BlobBuffer &lhs, const BlobBuffer &rhs)
bool operator==(const BlobBuffer &lhs, const BlobBuffer &rhs)
Definition balxml_encoderoptions.h:68
Definition bdlbb_blob.h:576
Definition bslma_usesbslmaallocator.h:343
Definition bslmf_isbitwisemoveable.h:718
Definition bslmf_movableref.h:791
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1060