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