BDE 4.39.x Production Release
Loading...
Searching...
No Matches
bdlc_queue.h
Go to the documentation of this file.
1/// @file bdlc_queue.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlc_queue.h -*-C++-*-
8#ifndef INCLUDED_BDLC_QUEUE
9#define INCLUDED_BDLC_QUEUE
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlc_queue bdlc_queue
15/// @brief <span style="color: var(--deprecated-color-dark)">DEPRECATED:</span> Provide an in-place double-ended queue of `T` values.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlc
19/// @{
20/// @addtogroup bdlc_queue
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlc_queue-purpose"> Purpose</a>
25/// * <a href="#bdlc_queue-classes"> Classes </a>
26/// * <a href="#bdlc_queue-description"> Description </a>
27/// * <a href="#bdlc_queue-abstract-representation"> Abstract Representation </a>
28/// * <a href="#bdlc_queue-performance"> Performance </a>
29/// * <a href="#bdlc_queue-usage"> Usage </a>
30/// * <a href="#bdlc_queue-example-1-basic-usage"> Example 1: Basic Usage </a>
31///
32/// # Purpose {#bdlc_queue-purpose}
33/// Provide an in-place double-ended queue of `T` values.
34///
35/// @deprecated Use @ref bsl::deque instead.
36///
37/// # Classes {#bdlc_queue-classes}
38///
39/// - bdlc::Queue: memory manager for in-place queue of `T` values
40///
41/// # Description {#bdlc_queue-description}
42/// This component implements an efficient, in-place, indexable,
43/// double-ended queue of `T` values, where `T` is a templatized, user-defined
44/// type. The functionality of a `bdlc::Queue` is relatively rich; it is almost
45/// a proper superset of a vector, with efficient implementations of `front`,
46/// `back`, `pushFront`, and `popBack` methods added. However, the queue does
47/// *not* provide a `data` method (yielding direct access to the underlying
48/// memory), because its internal organization is not array-like.
49///
50/// Typical usage involves pushing (appending) values to the back of the queue,
51/// popping (removing) values from the front of the queue, and retrieving
52/// (operator[]) values from a specified index; unlike the O[n] runtime cost for
53/// an `insert(0, v)`, however, a `pushFront` has a constant average-case cost.
54///
55/// Note that appending, inserting, removing or pushing (back and front)
56/// elements potentially alters the memory address of other element in the
57/// queue, and there is no guarantee of contiguous storage of consecutive queued
58/// elements.
59///
60/// ## Abstract Representation {#bdlc_queue-abstract-representation}
61///
62///
63/// The logical organization of an indexable, in-place, double-ended
64/// `bdlc::Queue` object `q` is shown below, along with an illustration of some
65/// of its most common methods:
66/// @code
67/// QUEUE
68/// v = q.front() v = q.back()
69/// +------+------+------+------+--//--+------+
70/// q.popFront() <-| | | | | | |<- pushBack(v)
71/// q.pushFront(v) ->| | | | | | |-> popBack()
72/// +------+------+------+------+--//--+------+
73/// q[0] q[1] q[n-1]
74/// <------------ n = q.length() --//--------->
75/// @endcode
76///
77/// ## Performance {#bdlc_queue-performance}
78///
79///
80/// The following characterizes the performance of representative operations
81/// using big-oh notation, O[f(N,M)], where the names `N` and `M` also refer to
82/// the number of respective elements in each container (i.e., its `length`).
83/// Here the average case, A[f(N)], is the amortized cost, which is defined as
84/// the cost of `N` successive invocations of the operation divided by `N`.
85/// @code
86/// Operation Worst Case Average Case
87/// --------- ---------- ------------
88/// DEFAULT CTOR O[1]
89/// COPY CTOR(N) O[N]
90/// N.DTOR() O[1]
91/// N.OP=(M) O[M]
92/// OP==(N,M) O[min(N,M)]
93///
94/// N.pushFront(value) O[N] A[1]
95/// N.pushBack(value) O[N] A[1]
96/// N.popFront() O[1]
97/// N.popBack() O[1]
98///
99/// N.append(value) O[N] A[1]
100/// N.insert(value) O[N]
101/// N.replace(value) O[1]
102/// N.remove(index) O[N]
103///
104/// N.OP@ref bdlc_queue O[1]
105/// N.length() O[1]
106/// @endcode
107///
108/// ## Usage {#bdlc_queue-usage}
109///
110///
111/// This section illustrates intended use of this component.
112///
113/// ### Example 1: Basic Usage {#bdlc_queue-example-1-basic-usage}
114///
115///
116/// The following snippets of code illustrate how to create and use a queue.
117/// First, create an empty `bdlc::Queue<double>` `q` and populate it with two
118/// elements `E1` and `E2`.
119/// @code
120/// const double E1 = 100.01;
121/// const double E2 = 200.02;
122///
123/// bdlc::Queue<double> q; assert( 0 == q.length());
124///
125/// q.append(E1); assert( 1 == q.length());
126/// assert(E1 == q[0]);
127/// assert(E1 == q.front());
128/// assert(E1 == q.back());
129///
130/// q.append(E2); assert( 2 == q.length());
131/// assert(E1 == q[0]);
132/// assert(E2 == q[1]);
133/// assert(E1 == q.front());
134/// assert(E2 == q.back());
135/// @endcode
136/// Now, pop the first element (`E1`) from `q` and push the same value to the
137/// front of the queue.
138/// @code
139/// q.popFront(); assert( 1 == q.length());
140/// assert(E2 == q[0]);
141/// assert(E2 == q.front());
142/// assert(E2 == q.back());
143///
144/// q.pushFront(E1); assert( 2 == q.length());
145/// assert(E1 == q[0]);
146/// assert(E2 == q[1]);
147/// assert(E1 == q.front());
148/// assert(E2 == q.back());
149/// @endcode
150/// Then, pop the last element (`E2`) from the back of `q` and push a new value
151/// `E3` at the end of the queue.
152/// @code
153/// const double E3 = 300.03;
154///
155/// q.popBack(); assert( 1 == q.length());
156/// assert(E1 == q[0]);
157/// assert(E1 == q.front());
158/// assert(E1 == q.back());
159///
160/// q.pushBack(E3); assert( 2 == q.length());
161/// assert(E1 == q[0]);
162/// assert(E3 == q[1]);
163/// assert(E1 == q.front());
164/// assert(E3 == q.back());
165/// @endcode
166/// Now, assign `E2` to the first element (index position 0) of `q`.
167/// @code
168/// q[0] = E2; assert( 2 == q.length());
169/// assert(E2 == q[0]);
170/// assert(E3 == q[1]);
171/// @endcode
172/// Then, insert a new value in the middle (index position 1) of `q`.
173/// @code
174/// const double E4 = 400.04;
175///
176/// q.insert(1, E4); assert( 3 == q.length());
177/// assert(E2 == q[0]);
178/// assert(E4 == q[1]);
179/// assert(E3 == q[2]);
180/// @endcode
181/// Next, iterate over the elements in `q`, printing them in increasing order of
182/// their index positions, `[0 .. q.length() - 1]`,
183/// @code
184/// bsl::cout << '[';
185/// int len = q.length();
186/// for (int i = 0; i < len; ++i) {
187/// bsl::cout << ' ' << q[i];
188/// }
189/// bsl::cout << " ]" << bsl::endl;
190///
191/// @endcode
192/// which produces the following output on `stdout`:
193/// @code
194/// [ 200.02 400.04 300.03 ]
195/// @endcode
196/// Finally, remove the elements from queue `q`.
197/// @code
198/// q.remove(2); assert( 2 == q.length());
199/// assert(E2 == q[0]);
200/// assert(E4 == q[1]);
201///
202/// q.remove(0); assert( 1 == q.length());
203/// assert(E4 == q[0]);
204///
205/// q.remove(0); assert( 0 == q.length());
206///
207/// @endcode
208/// Note that, in general, specifying index positions greater than or equal to
209/// length() will result in undefined behavior.
210/// @}
211/** @} */
212/** @} */
213
214/** @addtogroup bdl
215 * @{
216 */
217/** @addtogroup bdlc
218 * @{
219 */
220/** @addtogroup bdlc_queue
221 * @{
222 */
223
224#include <bdlscm_version.h>
225
226#include <bdlb_print.h>
227#include <bdlb_printmethods.h>
228
229#include <bslma_default.h>
231
233
236
237#include <bsl_cstring.h> // memmove(), memcmp(), memcpy()
238#include <bsl_ostream.h>
239#include <bsl_new.h>
240
241#ifndef BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
242#include <bslalg_typetraits.h>
243#endif // BDE_DONT_ALLOW_TRANSITIVE_INCLUDES
244
245
246namespace bdlc {
247
248 // ===========
249 // class Queue
250 // ===========
251
252/// This class implements an efficient, in-place double-ended queue of
253/// values of parameterized type `T`. The physical capacity of this queue
254/// may grow, but never shrinks. Capacity may be reserved initially via a
255/// constructor, or at any time thereafter by using the `reserveCapacity` and `reserveCapacityRaw` methods.
256///
257/// \note Note that there is no guarantee of
258/// contiguous storage of consecutive elements.
259///
260/// More generally, this container class supports a complete set of *value
261/// semantics* operations, including copy construction, assignment,
262/// equality comparison, `ostream` printing, and `bdex` serialization. (A
263/// precise operational definition of when two objects have the same value
264/// can be found in the description of `operator==` for the class.) This
265/// container is *exception neutral* with no guarantee of rollback: if an
266/// exception is thrown during the invocation of a method on a pre-existing
267/// object, the container is left in a valid state, but its value is
268/// undefined. In no event is memory leaked. Finally, *aliasing* (e.g.,
269/// using all or part of an object as both source and destination) is
270/// supported in all cases.
271///
272/// See @ref bdlc_queue
273template <class T>
274class Queue {
275
276 // PRIVATE TYPES
277 enum {
278 // The queue is full when 'd_front == d_back'. Hence, 'k_INITIAL_SIZE'
279 // must be at least two.
280
281 k_INITIAL_SIZE = 2, // initial physical capacity (in elements)
282 k_GROW_FACTOR = 2, // multiplicative factor for growing 'd_size'
283 k_EXTRA_CAPACITY = 2 // extra capacity needed by implementation
284 };
285
286 public:
287 // TYPES
288
289 /// Enable uniform use of an optional integral constructor argument to
290 /// specify the initial internal capacity (in elements). For example,
291 /// @code
292 /// Queue<unsigned int> x(Queue::InitialCapacity(8));
293 /// @endcode
294 /// instantiates an object `x` with an initial capacity of 8 elements,
295 /// but with a logical length of 0 elements.
296 ///
297 /// See @ref bdlc_queue
299
300 unsigned int d_i;
301
302 // CREATORS
303 explicit InitialCapacity(unsigned int i) : d_i(i) { }
305 };
306
307 private:
308 // DATA
309 T *d_array_p; // dynamically allocated array ('d_size'
310 // elements)
311
312 int d_size; // physical capacity of this array (in
313 // elements)
314
315 int d_front; // index of element before first stored
316 // element
317
318 int d_back; // index of element past last stored
319 // element
320
321 bslma::Allocator *d_allocator_p; // holds (but not own) memory allocator
322
323 private:
324 // PRIVATE MANIPULATORS
325
326 /// Grow geometrically the specified current `size` value while it is
327 /// less than the specified `minLength` value plus any additional
328 /// capacity required by the implementation (i.e., `k_EXTRA_CAPACITY`
329 /// elements). Return the new size value.
330 ///
331 /// \pre The behavior is undefined unless `k_INITIAL_SIZE <= size` and `0 <= minLength`.
332 /// \note Note that if
333 /// `minLength + k_EXTRA_CAPACITY <= size` then `size` is returned.
334 int calculateSufficientSize(int minLength, int size);
335
336 /// Copy efficiently the specified `numElements` data values from the
337 /// specified `srcArray` of the specified `srcSize` starting at the
338 /// specified `srcIndex` into the specified `dstArray` of the specified
339 /// `dstSize` starting at the specified `dstIndex`. Return the new
340 /// value for the back of the queue. The `srcArray` and the `dstArray`
341 /// are assumed to be queues; they are circular which implies copy may
342 /// have to be broken into multiple parts since the underlying array is linear.
343 ///
344 /// \pre The behavior is undefined unless `0 <= dstSize`,
345 /// `0 <= dstIndex < dstSize`, `0 <= srcIndex < srcSize`,
346 /// `0 <= numElements`, `numElements <= dstSize - k_EXTRA_CAPACITY`, and
347 /// `numElements <= srcSize - k_EXTRA_CAPACITY` (the `k_EXTRA_CAPACITY`
348 /// accounts for the locations of `d_front` and `d_back`).
349 ///
350 /// \note Note that aliasing is not handled properly.
351 int memcpyCircular(T *dstArray,
352 int dstSize,
353 int dstIndex,
354 const T *srcArray,
355 int srcSize,
356 int srcIndex,
357 int numElements);
358
359 /// Copy efficiently the specified `numElements` data values from the
360 /// specified `array` of the specified `size` starting at the specified
361 /// index `srcIndex` to the specified `dstIndex` assuming the elements
362 /// are to be moved to the left (towards the front of the queue).
363 /// `array` is assumed to be a queue; it is circular.
364 ///
365 /// \pre The behavior is undefined unless `0 <= size`, `0 <= dstIndex < size`,
366 /// `0 <= srcIndex < size`, and `0 <= numElements <= size - k_EXTRA_CAPACITY`.
367 ///
368 /// \note Note that this
369 /// function is alias safe.
370 void memShiftLeft(T *array,
371 int size,
372 int dstIndex,
373 int srcIndex,
374 int numElements);
375
376 /// Copy efficiently the specified `numElements` data values from the
377 /// specified `array` of the specified `size` starting at the specified
378 /// index `srcIndex` to the specified `dstIndex` assuming the elements
379 /// are to be moved to the right (towards the back of the queue).
380 /// `array` is assumed to be a queue; it is circular.
381 ///
382 /// \pre The behavior is undefined unless `0 <= size`, `0 <= dstIndex < size`,
383 /// `0 <= srcIndex < size`, and `0 <= numElements <= size - k_EXTRA_CAPACITY`.
384 ///
385 /// \note Note that this
386 /// function is alias safe.
387 void memShiftRight(T *array,
388 int size,
389 int dstIndex,
390 int srcIndex,
391 int numElements);
392
393 /// Copy efficiently the queue indicated by the specified `srcArray` of
394 /// the specified `srcSize` with the specified `srcFront` and the
395 /// specified `srcBack` into the queue indicated by the specified
396 /// `dstArray` of the specified `dstSize`, with the specified
397 /// `dstFront`. The specified `dstBack` is set to make the length of
398 /// the destination queue the same as the length of the source queue.
399 ///
400 /// \pre The behavior is undefined unless `0 <= dstSize`,
401 /// `0 <= dstFront < dstSize`, `0 <= srcSize`,
402 /// `0 <= srcFront < srcSize`, and `0 <= srcBack < srcSize`.
403 ///
404 /// \note Note that aliasing is not handled properly.
405 void copyData(T *dstArray,
406 int *dstBack,
407 int dstSize,
408 int dstFront,
409 const T *srcArray,
410 int srcSize,
411 int srcFront,
412 int srcBack);
413
414 /// Increase the physical capacity of the queue represented by the
415 /// specified `addrArray` to specified `newSize` from the specified
416 /// `size`. Return the new size of the queue. This function copies the
417 /// data contained within the queue between the specified `front` and
418 /// `back` to the new queue and update the values of both `front` and
419 /// `back`. Use the specified `allocator` to supply and retrieve memory.
420 ///
421 /// \pre The behavior is undefined unless
422 /// `k_INITIAL_SIZE <= newSize`, `k_INITIAL_SIZE <= size`,
423 /// `size <= newSize`, `0 <= *front < size`, and `0 <= *back < size`.
424 int increaseSizeImp(T **addrArray,
425 int *front,
426 int *back,
427 int newSize,
428 int size,
429 bslma::Allocator *allocator);
430
431 /// Increase the physical capacity of this array by at least one
432 /// element.
433 void increaseSize();
434
435 public:
436 // TRAITS
439
440 // CLASS METHODS
441
442 /// Return the maximum valid BDEX format version, as indicated by the
443 /// specified `versionSelector`, to be passed to the `bdexStreamOut` method.
444 ///
445 /// \note Note that it is highly recommended that `versionSelector`
446 /// be formatted as "YYYYMMDD", a date representation. Also note that
447 /// `versionSelector` should be a *compile*-time-chosen value that
448 /// selects a format version supported by both externalizer and
449 /// unexternalizer. See the `bslx` package-level documentation for more
450 /// information on BDEX streaming of value-semantic types and
451 /// containers.
452 static int maxSupportedBdexVersion(int versionSelector);
453
454 // CREATORS
455
456 /// Create an in-place queue. By default, the queue is empty.
457 /// Optionally specify the `initialLength` of the queue. Queue elements
458 /// are initialized with the specified `initialValue`, or to 0.0 if
459 /// `initialValue` is not specified. Optionally specify a
460 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
461 /// the currently installed default allocator is used.
462 ///
463 /// \pre The behavior is undefined unless `0 <= initialLength`.
464 explicit
465 Queue(bslma::Allocator *basicAllocator = 0);
466 explicit
467 Queue(unsigned int initialLength,
468 bslma::Allocator *basicAllocator = 0);
469 Queue(int initialLength,
470 const T& initialValue,
471 bslma::Allocator *basicAllocator = 0);
472
473 /// Create an in-place queue with sufficient initial capacity to
474 /// accommodate up to the specified `numElements` values without
475 /// subsequent reallocation. A valid reference returned by the
476 /// `operator[]` method is guaranteed to remain valid unless the value
477 /// returned by the `length` method exceeds `numElements` (which would
478 /// potentially cause a reallocation). Optionally specify a
479 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
480 /// the currently installed default allocator is used.
481 ///
482 /// \pre The behavior is undefined unless `0 <= numElements`.
483 explicit
484 Queue(const InitialCapacity& numElements,
485 bslma::Allocator *basicAllocator = 0);
486
487 /// Create an in-place queue initialized with the specified
488 /// `numElements` leading values from the specified `srcArray`.
489 /// Optionally specify the `basicAllocator` used to supply memory. If
490 /// `basicAllocator` is 0, the currently installed default allocator is used.
491 ///
492 /// \pre The behavior is undefined unless `0 <= numElements`.
493 ///
494 /// \note Note that `srcArray` must refer to sufficient memory to hold
495 /// `numElements` values.
496 Queue(const T *srcArray,
497 int numElements,
498 bslma::Allocator *basicAllocator = 0);
499
500 /// Create an in-place queue initialized to the value of the specified
501 /// `original` queue. Optionally specify the `basicAllocator` used to
502 /// supply memory. If `basicAllocator` is 0, the currently installed
503 /// default allocator is used.
504 Queue(const Queue& original, bslma::Allocator* basicAllocator = 0);
505
506 /// Destroy this object.
508
509 // MANIPULATORS
510
511 /// Assign to this queue the value of the specified `rhs` queue and
512 /// return a reference to this modifiable queue.
513 Queue& operator=(const Queue& rhs);
514
515 /// Return a reference to the modifiable element at the specified
516 /// `index` position in this queue. The reference will remain valid as
517 /// long as this queue is not destroyed or modified (e.g., via `insert`, `remove`, or `append`).
518 ///
519 /// \pre The behavior is undefined unless
520 /// `0 <= index < length()`.
521 T& operator[](int index);
522
523 /// Append to the end of this queue the value of the specified `item`.
524 ///
525 /// \note Note that this function is a synonym for `pushBack` and is logically
526 /// equivalent to (but generally more efficient than):
527 /// @code
528 /// insert(length(), item);
529 /// @endcode
530 void append(const T& item);
531
532 /// Append to the end of this queue the sequence of values in the specified `srcQueue`.
533 ///
534 /// \note Note that this function is logically
535 /// equivalent to:
536 /// @code
537 /// insert(length(), srcQueue);
538 /// @endcode
539 void append(const Queue& srcQueue);
540
541 /// Append to the end of this queue the specified `numElements` value in
542 /// the specified `srcQueue` starting at the specified index position `srcIndex`.
543 ///
544 /// \note Note that this function is logically equivalent to:
545 /// @code
546 /// insert(length(), srcQueue, srcIndex, numElements);
547 /// @endcode
548 ///
549 /// \pre The behavior is undefined unless `0 <= srcIndex`,
550 /// `0 <= numElements`, and
551 /// `srcIndex + numElements <= srcQueue.length()`.
552 void append(const Queue& srcQueue, int srcIndex, int numElements);
553
554 /// Return a reference to the modifiable value at the back of this
555 /// queue. The reference will remain valid as long as the queue is not
556 /// destroyed or modified (e.g., via `insert`, `remove`, or `append`).
557 ///
558 /// \pre The behavior is undefined if the queue is empty.
559 /// \note Note that this
560 /// function is logically equivalent to:
561 /// @code
562 /// operator[](length() - 1)
563 /// @endcode
564 T& back();
565
566 /// Return a reference to the modifiable value at the front of this
567 /// queue. The reference will remain valid as long as the queue is not
568 /// destroyed or modified (e.g., via `insert`, `remove`, or `append`).
569 ///
570 /// \pre The behavior is undefined if the queue is empty.
571 /// \note Note that this
572 /// function is logically equivalent to:
573 /// @code
574 /// operator[](0)
575 /// @endcode
576 T& front();
577
578 /// Insert the specified `item` into this queue at the specified
579 /// `dstIndex`. All current values with indices at or above `dstIndex`
580 /// are shifted up by one index position.
581 ///
582 /// \pre The behavior is undefined unless `0 <= dstIndex <= length()`.
583 void insert(int dstIndex, const T& item);
584
585 /// Insert the specified `srcQueue` into this queue at the specified
586 /// `dstIndex`. All current values with indices at or above `dstIndex`
587 /// are shifted up by `srcQueue.length()` index positions.
588 ///
589 /// \pre The behavior is undefined unless `0 <= dstIndex <= length()`.
590 void insert(int dstIndex, const Queue& srcQueue);
591
592 /// Insert the specified `numElements` values starting at the specified
593 /// `srcIndex` position from the specified `srcQueue` into this queue at
594 /// the specified `dstIndex`. All current values with indices at or
595 /// above `dstIndex` are shifted up by `numElements` index positions.
596 ///
597 /// \pre The behavior is undefined unless `0 <= dstIndex <= length()`,
598 /// `0 <= srcIndex`, `0 <= numElements`, and
599 /// `srcIndex + numElements <= srcQueue.length()`.
600 void insert(int dstIndex,
601 const Queue& srcQueue,
602 int srcIndex,
603 int numElements);
604
605 /// Remove the value from the back of this queue efficiently (in O[1] time).
606 ///
607 /// \pre The behavior is undefined if this queue is empty.
608 ///
609 /// \note Note that this function is logically equivalent to (but more efficient than):
610 /// @code
611 /// remove(length() - 1)
612 /// @endcode
613 void popBack();
614
615 /// Remove the value from the front of this queue efficiently (in O[1] time).
616 ///
617 /// \pre The behavior is undefined if this queue is empty.
618 ///
619 /// \note Note that this function is logically equivalent to (but more efficient than):
620 /// @code
621 /// remove(0)
622 /// @endcode
623 void popFront();
624
625 /// Append the specified `item` to the back of this queue efficiently
626 /// (in O[1] time when memory reallocation is not required).
627 ///
628 /// \note Note that this function is logically equivalent to (but generally more
629 /// efficient than):
630 /// @code
631 /// insert(length(), item);
632 /// @endcode
633 void pushBack(const T& item);
634
635 /// Insert the specified `item` into the front of this queue efficiently
636 /// (in O[1] time when memory reallocation is not required).
637 ///
638 /// \note Note that this function is logically equivalent to (but generally more
639 /// efficient than):
640 /// @code
641 /// insert(0, item);
642 /// @endcode
643 void pushFront(const T& item);
644
645 /// Remove from this queue the value at the specified `index`. All
646 /// values with initial indices above `index` are shifted down by one index position.
647 ///
648 /// \pre The behavior is undefined unless
649 /// `0 <= index < length()`.
650 void remove(int index);
651
652 /// Remove from this queue, beginning at the specified `index`, the
653 /// specified `numElements` values. All values with initial indices at
654 /// or above `index + numElements` are shifted down by `numElements` index positions.
655 ///
656 /// \pre The behavior is undefined unless `0 <= index`,
657 /// `0 <= numElements`, and `index + numElements <= length()`.
658 void remove(int index, int numElements);
659
660 /// Remove all elements from this queue. If the optionally specified
661 /// `buffer` is not 0, append to `buffer` a copy of each element removed
662 /// (in front-to-back order of the elements in the queue prior to the
663 /// invocation of this method).
664 void removeAll(bsl::vector<T> *buffer = 0);
665
666 /// Replace the element at the specified `dstIndex` in this queue with the specified `item`.
667 ///
668 /// \pre The behavior is undefined unless `0 <= dstIndex < length()`.
669 ///
670 /// \note Note that this function is logically
671 /// equivalent to (but more efficient than):
672 /// @code
673 /// insert(dstIndex, item);
674 /// remove(dstIndex + 1);
675 /// @endcode
676 void replace(int dstIndex, const T& item);
677
678 /// Replace the specified `numElements` values beginning at the
679 /// specified `dstIndex` in this queue with values from the specified
680 /// `srcQueue` beginning at the specified `srcIndex`.
681 ///
682 /// \pre The behavior is undefined unless `0 <= dstIndex, 0 <= numElements`,
683 /// `dstIndex + numElements <= length()`, `0 <= srcIndex`, and `srcIndex + numElements <= srcQueue.length()`.
684 ///
685 /// \note Note that this
686 /// function is logically equivalent to (but more efficient than):
687 /// @code
688 /// insert(dstIndex, srcQueue, srcIndex, numElements);
689 /// remove(dstIndex + numElements, numElements);
690 /// @endcode
691 void replace(int dstIndex,
692 const Queue& srcQueue,
693 int srcIndex,
694 int numElements);
695
696 /// Reserve sufficient internal capacity to accommodate up to the
697 /// specified `numElements` values without subsequent reallocation.
698 ///
699 /// \note Note that if `numElements <= length()`, this operation has no
700 /// effect.
701 void reserveCapacity(int numElements);
702
703 /// Reserve sufficient and minimal internal capacity to accommodate up
704 /// to the specified `numElements` values without subsequent
705 /// reallocation. Beware, however, that repeated calls to this function
706 /// may invalidate bounds on runtime complexity otherwise guaranteed by this container.
707 ///
708 /// \note Note that if `numElements <= length()`, this
709 /// operation has no effect.
710 void reserveCapacityRaw(int numElements);
711
712 /// Set the length of this queue to the specified `newLength`. If
713 /// `newLength` is less than the current length, elements at index
714 /// positions at or above `newLength` are removed. Otherwise any new
715 /// elements (at or above the current length) are initialized to the
716 /// specified `initialValue`, or to 0.0 if `initialValue` is not specified.
717 ///
718 /// \pre The behavior is undefined unless `0 <= newLength`.
719 void setLength(int newLength);
720 void setLength(int newLength, const T& initialValue);
721
722 /// Set the length of this queue to the specified `newLength`. If
723 /// `newLength` is less than the current length, elements at index
724 /// positions at or above `newLength` are removed. If `newLength` is
725 /// equal to the current length, this function has no effect. Otherwise
726 /// new elements at or above the current length are not initialized to
727 /// any value.
728 void setLengthRaw(int newLength);
729
730 /// Assign to this object the value read from the specified input
731 /// `stream` using the specified `version` format, and return a
732 /// reference to `stream`. If `stream` is initially invalid, this
733 /// operation has no effect. If `version` is not supported, this object
734 /// is unaltered and `stream` is invalidated, but otherwise unmodified.
735 /// If `version` is supported but `stream` becomes invalid during this
736 /// operation, this object has an undefined, but valid, state.
737 ///
738 /// \note Note that no version is read from `stream`. See the `bslx` package-level
739 /// documentation for more information on BDEX streaming of
740 /// value-semantic types and containers.
741 template <class STREAM>
742 STREAM& bdexStreamIn(STREAM& stream, int version);
743
744 /// Swap efficiently the values at the specified indices `index1` and `index2`.
745 ///
746 /// \pre The behavior is undefined unless `0 <= index1 < length()`
747 /// and `0 <= index2 < length()`.
748 void swap(int index1, int index2);
749
750 // ACCESSORS
751
752 /// Return a reference to the non-modifiable element at the specified
753 /// `index` position in this queue. The reference will remain valid as
754 /// long as this queue is not destroyed or modified (e.g., via `insert`, `remove`, or `append`).
755 ///
756 /// \pre The behavior is undefined unless
757 /// `0 <= index < length()`.
758 const T& operator[](int index) const;
759
760 /// Return a reference to the non-modifiable element at the back of this
761 /// queue. The reference will remain valid as long as this queue is not
762 /// destroyed or modified (e.g., via `insert`, `remove`, or `append`).
763 ///
764 /// \pre The behavior is undefined if this queue is empty.
765 /// \note Note that this
766 /// function is logically equivalent to:
767 /// @code
768 /// operator[](length() - 1)
769 /// @endcode
770 const T& back() const;
771
772 /// Return a reference to the non-modifiable element at the front of
773 /// this queue. The reference will remain valid as long as this queue
774 /// is not destroyed or modified (e.g., via `insert`, `remove`, or `append`).
775 ///
776 /// \pre The behavior is undefined if this queue is empty.
777 ///
778 /// \note Note that this function is logically equivalent to:
779 /// @code
780 /// operator[](0)
781 /// @endcode
782 const T& front() const;
783
784 /// Return the number of elements in this queue.
785 int length() const;
786
787 /// Format this object to the specified output `stream` at the
788 /// optionally specified indentation `level` and return a reference to
789 /// the modifiable `stream`. If `level` is specified, optionally
790 /// specify `spacesPerLevel`, the number of spaces per indentation level
791 /// for this and all of its nested objects. Each line is indented by
792 /// the absolute value of `level * spacesPerLevel`. If `level` is
793 /// negative, suppress indentation of the first line. If
794 /// `spacesPerLevel` is negative, suppress line breaks and format the
795 /// entire output on one line. If `stream` is initially invalid, this operation has no effect.
796 ///
797 /// \note Note that a trailing newline is provided
798 /// in multi-line mode only.
799 bsl::ostream& print(bsl::ostream& stream,
800 int level,
801 int spacesPerLevel) const;
802
803 /// Write the elements of this queue out to the specified `stream`.
804 ///
805 /// \note Note that for this method to compile, `operator<<` has to be defined
806 /// for arguments `stream` and type `T`.
807 bsl::ostream& streamOut(bsl::ostream& stream) const
808 {
809 stream << '[';
810 for (int i = 0; i < length(); ++i) {
811 stream << ' ' << (*this)[i];
812 }
813 return stream << " ]";
814 }
815
816 /// Write the value of this object, using the specified `version`
817 /// format, to the specified output `stream`, and return a reference to
818 /// `stream`. If `stream` is initially invalid, this operation has no
819 /// effect. If `version` is not supported, `stream` is invalidated, but otherwise unmodified.
820 ///
821 /// \note Note that `version` is not written to
822 /// `stream`. See the `bslx` package-level documentation for more
823 /// information on BDEX streaming of value-semantic types and
824 /// containers.
825 template <class STREAM>
826 STREAM& bdexStreamOut(STREAM& stream, int version) const;
827
828#ifndef BDE_OMIT_INTERNAL_DEPRECATED
829 /// Return the most current BDEX streaming version number supported by
830 /// this class.
831 ///
832 /// @deprecated Use @ref maxSupportedBdexVersion(int) instead.
834
835 /// Return the most current `bdex` streaming version number supported by
836 /// this class. (See the package-group-level documentation for more
837 /// information on `bdex` streaming of container types.)
838 ///
839 /// @deprecated Use @ref maxSupportedBdexVersion instead.
841
842#endif // BDE_OMIT_INTERNAL_DEPRECATED
843};
844
845// FREE OPERATORS
846
847/// Return `true` if the specified `lhs` and `rhs` queues have the same
848/// value, and `false` otherwise. Two queues have the same value if they
849/// have the same length and the same element value at each respective index
850/// position.
851template <class T>
852inline
853bool operator==(const Queue<T>& lhs, const Queue<T>& rhs);
854
855/// Return `true` if the specified `lhs` and `rhs` queues do not have the
856/// same value, and `false` otherwise. Two queues do not have the same
857/// value if they have different lengths or differ in at least one index
858/// position.
859template <class T>
860inline
861bool operator!=(const Queue<T>& lhs, const Queue<T>& rhs);
862
863/// Write the specified `queue` to the specified output `stream` and return
864/// a reference to the modifiable `stream`.
865template <class T>
866inline
867bsl::ostream& operator<<(bsl::ostream& stream, const Queue<T>& queue);
868
869// ============================================================================
870// INLINE DEFINITIONS
871// ============================================================================
872
873// TBD pass through allocator
874// TBD isBitwise, etc.
875
876 // ---------------------------------------------
877 // inlined methods used by other inlined methods
878 // ---------------------------------------------
879
880template <class T>
881inline
883{
884 return d_back > d_front ? d_back - d_front - 1
885 : d_back + d_size - d_front - 1;
886}
887
888// PRIVATE MANIPULATORS
889template <class T>
890int Queue<T>::calculateSufficientSize(int minLength, int size)
891{
892 const int len = minLength + k_EXTRA_CAPACITY;
893 while (size < len) {
894 size *= k_GROW_FACTOR;
895 }
896 return size;
897}
898
899template <class T>
900int Queue<T>::memcpyCircular(T *dstArray,
901 int dstSize,
902 int dstIndex,
903 const T *srcArray,
904 int srcSize,
905 int srcIndex,
906 int numElements)
907{
908 int dst; // temporary value to store the current destination location
909
910 // Break the source queue into one or two linear arrays to copy.
911
912 int srcA = srcIndex;
913 if (srcA + numElements <= srcSize) { // one linear source array
914 int lenSrcA = numElements;
915
916 dst = dstIndex;
917
918 // Compute the maximum number of elements that can be copied to the
919 // destination array.
920
921 int dstLen = dstSize - dst;
922
923 if (dstLen >= lenSrcA) { // can copy everything from srcA
924 // TBD efficiency
925
926 for (int i = 0; i < lenSrcA; ++i) {
927 new (&dstArray[dst + i]) T(srcArray[srcA + i]);
928 }
929 dst += lenSrcA;
930 }
931 else { // can copy only part of srcA without changing dst
932 // TBD efficiency
933
934 for (int i = 0; i < dstLen; ++i) {
935 new (&dstArray[dst + i]) T(srcArray[srcA + i]);
936 }
937 srcA += dstLen;
938 lenSrcA -= dstLen;
939
940 // WARNING: There seems to be an AIX compiler issue for the
941 // following four lines. Removing the 'assert' and moving the
942 // 'memcpy' down two lines may cause the program to compile, but
943 // not execute properly.
944
945 // TBD efficiency
946
947 for (int i = 0; i < lenSrcA; ++i) {
948 new (&dstArray[i]) T(srcArray[srcA + i]);
949 }
950 dstLen = dst; // max numElements that can be copied to index 0
951 dst = lenSrcA;
952
953 // TBD doc above assert(lenSrcA <= dstLen - k_EXTRA_CAPACITY);
954 }
955 }
956 else { // two linear source arrays
957 int lenSrcA = srcSize - srcA;
958 int lenSrcB = numElements - lenSrcA;
959
960 dst = dstIndex;
961
962 // Compute the maximum number of elements that can be copied to the
963 // destination array.
964
965 int dstLen = dstSize - dst;
966
967 if (dstLen >= lenSrcA) { // can copy everything from srcA
968 // TBD efficiency
969
970 for (int i = 0; i < lenSrcA; ++i) {
971 new (&dstArray[dst + i]) T(srcArray[srcA + i]);
972 }
973 dst += lenSrcA;
974 }
975 else { // can copy only part of srcA without changing dst
976 // TBD efficiency
977
978 for (int i = 0; i < dstLen; ++i) {
979 new (&dstArray[dst + i]) T(srcArray[srcA + i]);
980 }
981 srcA += dstLen;
982 lenSrcA -= dstLen;
983
984 // WARNING: There seems to be an AIX compiler issue for the
985 // following four lines. Removing the 'assert' and moving the
986 // 'memcpy' down two lines may cause the program to compile, but
987 // not execute properly.
988
989 // TBD efficiency
990
991 for (int i = 0; i < lenSrcA; ++i) {
992 new (&dstArray[i]) T(srcArray[srcA + i]);
993 }
994 dstLen = dst; // max numElements that can be copied to index 0
995 dst = lenSrcA;
996
997 // TBD
998 // doc above assert(
999 // lenSrcA + lenSrcB <= dstLen - k_EXTRA_CAPACITY);
1000 }
1001 dstLen -= lenSrcA;
1002
1003 if (dstLen >= lenSrcB) { // can copy everything from srcB
1004 // TBD efficiency
1005
1006 for (int i = 0; i < lenSrcB; ++i) {
1007 new (&dstArray[dst + i]) T(srcArray[i]);
1008 }
1009 dst += lenSrcB;
1010 }
1011 else { // can copy only part of srcB without changing dst
1012 // NOTE: could not have had insufficient room for srcA
1013 // TBD efficiency
1014
1015 for (int i = 0; i < dstLen; ++i) {
1016 new (&dstArray[dst + i]) T(srcArray[i]);
1017 }
1018 lenSrcB -= dstLen;
1019 dst = lenSrcB;
1020
1021 // TBD efficiency
1022
1023 for (int i = 0; i < lenSrcB; ++i) {
1024 new (&dstArray[i]) T(srcArray[dstLen + i]);
1025 }
1026 }
1027 }
1028
1029 return dst % dstSize;
1030}
1031
1032template <class T>
1033void Queue<T>::memShiftLeft(T *array,
1034 int size,
1035 int dstIndex,
1036 int srcIndex,
1037 int numElements)
1038{
1039 // Move the elements that do not wrap around the array end.
1040
1041 if (srcIndex > dstIndex) {
1042 int numMove = size - srcIndex;
1043 if (numMove >= numElements) {
1044 // TBD efficiency
1045
1046 for (int i = 0; i < numElements; ++i) {
1047 new (&array[dstIndex + i]) T(array[srcIndex + i]);
1048 array[srcIndex + i].~T();
1049 }
1050 return; // RETURN
1051 }
1052
1053 // TBD efficiency
1054
1055 for (int i = 0; i < numMove; ++i) {
1056 new (&array[dstIndex + i]) T(array[srcIndex + i]);
1057 array[srcIndex + i].~T();
1058 }
1059 numElements -= numMove;
1060 dstIndex += numMove;
1061 srcIndex = 0;
1062 }
1063 else if (srcIndex == dstIndex) {
1064 return; // RETURN
1065 }
1066
1067 // Move the elements of the source that will just precede the array end.
1068
1069 int numMove = size - dstIndex;
1070 if (numMove >= numElements) {
1071 // TBD efficiency
1072
1073 for (int i = numElements - 1; i >= 0; --i) {
1074 new (&array[dstIndex + i]) T(array[srcIndex + i]);
1075 array[srcIndex + i].~T();
1076 }
1077
1078 return; // RETURN
1079 }
1080 // TBD efficiency
1081
1082 for (int i = numMove - 1; i >= 0; --i) {
1083 new (&array[dstIndex + i]) T(array[srcIndex + i]);
1084 array[srcIndex + i].~T();
1085 }
1086 numElements -= numMove;
1087 srcIndex += numMove;
1088
1089 // Move the elements of the source that are around the array end.
1090
1091 // TBD efficiency
1092
1093 for (int i = 0; i < numElements; ++i) {
1094 new (&array[i]) T(array[srcIndex + i]);
1095 array[srcIndex + i].~T();
1096 }
1097}
1098
1099template <class T>
1100void Queue<T>::memShiftRight(T *array,
1101 int size,
1102 int dstIndex,
1103 int srcIndex,
1104 int numElements)
1105{
1106 if (dstIndex == srcIndex) {
1107 return; // RETURN
1108 }
1109
1110 {
1111
1112 // Move the elements of the source that wrap around the array end.
1113
1114 int numMove = srcIndex + numElements;
1115 if (numMove > size) {
1116 numMove -= size;
1117 // TBD efficiency
1118
1119 for (int i = numMove - 1; i >= 0; --i) {
1120 new (&array[(dstIndex + numElements - numMove) % size + i])
1121 T(array[i]);
1122 array[i].~T();
1123 }
1124 numElements -= numMove;
1125 }
1126 }
1127
1128 {
1129 // Move the elements of the source that will wrap around the array end.
1130
1131 int numMove = dstIndex + numElements;
1132 if (numMove > size) {
1133 numMove -= size;
1134 // TBD efficiency
1135
1136 for (int i = 0; i < numMove; ++i) {
1137 new (&array[i])
1138 T(array[(srcIndex + numElements - numMove) % size + i]);
1139 array[srcIndex + numElements - numMove + i].~T();
1140 }
1141 numElements -= numMove;
1142 }
1143 }
1144
1145 // Move the elements of the source that do not and will not wrap around
1146 // the array end.
1147
1148 if (dstIndex < srcIndex) {
1149 // TBD efficiency
1150
1151 for (int i = 0; i < numElements; ++i) {
1152 new (&array[dstIndex + i]) T(array[srcIndex + i]);
1153 array[srcIndex + i].~T();
1154 }
1155 }
1156 else {
1157 // TBD efficiency
1158
1159 for (int i = numElements - 1; i >= 0; --i) {
1160 new (&array[dstIndex + i]) T(array[srcIndex + i]);
1161 array[srcIndex + i].~T();
1162 }
1163 }
1164}
1165
1166template <class T>
1167inline
1168void Queue<T>::copyData(T *dstArray,
1169 int *dstBack,
1170 int dstSize,
1171 int dstFront,
1172 const T *srcArray,
1173 int srcSize,
1174 int srcFront,
1175 int srcBack)
1176{
1177 const int dstIndex = (dstFront + 1) % dstSize;
1178 const int srcIndex = (srcFront + 1) % srcSize;
1179 const int numElements = (srcBack + srcSize - srcFront - 1) % srcSize;
1180
1181 *dstBack = memcpyCircular(dstArray,
1182 dstSize,
1183 dstIndex,
1184 srcArray,
1185 srcSize,
1186 srcIndex,
1187 numElements);
1188}
1189
1190template <class T>
1191int Queue<T>::increaseSizeImp(T **addrArray,
1192 int *front,
1193 int *back,
1194 int newSize,
1195 int size,
1196 bslma::Allocator *allocator)
1197{
1198 T *array = (T *)allocator->allocate(newSize * sizeof **addrArray);
1199
1200 // COMMIT
1201
1202 const int oldFront = *front;
1203 const int oldBack = *back;
1204 *front = newSize - 1;
1205 copyData(array, back, newSize, *front, *addrArray, size, oldFront, *back);
1206
1207 // TBD efficiency
1208
1209 for (int i = (oldFront + 1) % size; i != oldBack; i = (i + 1) % size) {
1210 (*addrArray)[i].~T();
1211 }
1212
1213 allocator->deallocate(*addrArray);
1214 *addrArray = array;
1215 return newSize;
1216}
1217
1218template <class T>
1219inline
1220void Queue<T>::increaseSize()
1221{
1222 d_size = increaseSizeImp(&d_array_p,
1223 &d_front,
1224 &d_back,
1225 d_size * k_GROW_FACTOR,
1226 d_size,
1227 d_allocator_p);
1228}
1229
1230// CLASS METHODS
1231template <class T>
1232inline
1233int Queue<T>::maxSupportedBdexVersion(int /* versionSelector */)
1234{
1235 return 1; // Required by BDE policy; versions start at 1.
1236}
1237
1238#ifndef BDE_OMIT_INTERNAL_DEPRECATED // pending deprecation
1239
1240// DEPRECATED METHODS
1241
1242template <class T>
1243inline
1245{
1246 return maxSupportedBdexVersion();
1247}
1248
1249template <class T>
1250inline
1252{
1253 return 1; // Required by BDE policy; versions start at 1.
1254}
1255
1256#endif // BDE_OMIT_INTERNAL_DEPRECATED -- pending deprecation
1257
1258// CREATORS
1259template <class T>
1261: d_size(k_INITIAL_SIZE)
1262, d_front(k_INITIAL_SIZE - 1)
1263, d_back(0)
1264, d_allocator_p(bslma::Default::allocator(basicAllocator))
1265{
1266 d_array_p = (T *)d_allocator_p->allocate(d_size * sizeof *d_array_p);
1267}
1268
1269template <class T>
1270Queue<T>::Queue(unsigned int initialLength, bslma::Allocator *basicAllocator)
1271: d_back(initialLength)
1272, d_allocator_p(bslma::Default::allocator(basicAllocator))
1273{
1274 d_size = calculateSufficientSize(initialLength, k_INITIAL_SIZE);
1275 d_array_p = (T *)d_allocator_p->allocate(d_size * sizeof *d_array_p);
1276 d_front = d_size - 1;
1277
1278 // initialize the array values
1279 // TBD efficiency
1280 // TBD exception neutrality
1281
1282 for (int i = 0; i < d_back; ++i) {
1283 new (d_array_p + i) T();
1284 }
1285}
1286
1287template <class T>
1288Queue<T>::Queue(int initialLength,
1289 const T& initialValue,
1290 bslma::Allocator *basicAllocator)
1291: d_back(initialLength)
1292, d_allocator_p(bslma::Default::allocator(basicAllocator))
1293{
1294 d_size = calculateSufficientSize(initialLength, k_INITIAL_SIZE);
1295 d_array_p = (T *)d_allocator_p->allocate(d_size * sizeof *d_array_p);
1296 d_front = d_size - 1;
1297
1298 // TBD efficiency
1299 // TBD exception neutrality
1300
1301 for (int i = 0; i < d_back; ++i) {
1302 new (d_array_p + i) T(initialValue);
1303 }
1304}
1305
1306template <class T>
1308 bslma::Allocator *basicAllocator)
1309: d_size(numElements.d_i + k_EXTRA_CAPACITY) // to hold the empty positions
1310, d_front(numElements.d_i + k_EXTRA_CAPACITY - 1)
1311, d_back(0)
1312, d_allocator_p(bslma::Default::allocator(basicAllocator))
1313{
1314 d_array_p = (T *)d_allocator_p->allocate(d_size * sizeof *d_array_p);
1315}
1316
1317template <class T>
1318Queue<T>::Queue(const T *srcArray,
1319 int numElements,
1320 bslma::Allocator *basicAllocator)
1321: d_back(numElements)
1322, d_allocator_p(bslma::Default::allocator(basicAllocator))
1323{
1324 d_size = calculateSufficientSize(numElements, k_INITIAL_SIZE);
1325 d_front = d_size - 1;
1326 d_array_p = (T *)d_allocator_p->allocate(d_size * sizeof *d_array_p);
1327
1328 // TBD efficiency
1329
1330 for (int i = 0; i < numElements; ++i) {
1331 new (&d_array_p[i]) T(srcArray[i]);
1332 }
1333}
1334
1335template <class T>
1336Queue<T>::Queue(const Queue& original, bslma::Allocator *basicAllocator)
1337: d_allocator_p(bslma::Default::allocator(basicAllocator))
1338{
1339 d_size = calculateSufficientSize(original.length(), k_INITIAL_SIZE);
1340 d_array_p = (T *)d_allocator_p->allocate(d_size * sizeof *d_array_p);
1341 d_front = d_size - 1;
1342 copyData(d_array_p,
1343 &d_back,
1344 d_size,
1345 d_front,
1346 original.d_array_p,
1347 original.d_size,
1348 original.d_front,
1349 original.d_back);
1350}
1351
1352template <class T>
1354{
1355 // TBD efficiency
1356
1357 for (int i = (d_front + 1) % d_size; i != d_back; i = (i + 1) % d_size) {
1358 d_array_p[i].~T();
1359 }
1360
1361 d_allocator_p->deallocate(d_array_p);
1362}
1363
1364// MANIPULATORS
1365template <class T>
1367{
1368 if (this != &rhs) {
1369 const int newSize =
1370 calculateSufficientSize(rhs.length(), k_INITIAL_SIZE);
1371 if (newSize > d_size) {
1372 T *array =
1373 (T *)d_allocator_p->allocate(newSize * sizeof *d_array_p);
1374
1375 // TBD efficiency
1376
1377 for (int i = (d_front + 1) % d_size; i != d_back;
1378 i = (i + 1) % d_size) {
1379 d_array_p[i].~T();
1380 }
1381
1382 d_allocator_p->deallocate(d_array_p);
1383 d_array_p = array;
1384 d_size = newSize;
1385 }
1386 else {
1387 // TBD efficiency
1388
1389 for (int i = (d_front + 1) % d_size; i != d_back;
1390 i = (i + 1) % d_size) {
1391 d_array_p[i].~T();
1392 }
1393 }
1394 copyData(d_array_p,
1395 &d_back,
1396 d_size,
1397 d_front,
1398 rhs.d_array_p,
1399 rhs.d_size,
1400 rhs.d_front,
1401 rhs.d_back);
1402 }
1403 return *this;
1404}
1405
1406template <class T>
1407inline
1409{
1410 return d_array_p[(index + d_front + 1) % d_size];
1411}
1412
1413template <class T>
1414void Queue<T>::append(const Queue& srcQueue)
1415{
1416 const int numElements = srcQueue.length();
1417 const int newLength = length() + numElements;
1418 const int minSize = calculateSufficientSize(newLength, d_size);
1419 if (d_size < minSize) {
1420 d_size = increaseSizeImp(&d_array_p,
1421 &d_front,
1422 &d_back,
1423 minSize,
1424 d_size,
1425 d_allocator_p);
1426 }
1427 d_back = memcpyCircular(d_array_p,
1428 d_size,
1429 d_back,
1430 srcQueue.d_array_p,
1431 srcQueue.d_size,
1432 (srcQueue.d_front + 1) % srcQueue.d_size,
1433 numElements);
1434}
1435
1436template <class T>
1437void Queue<T>::append(const Queue& srcQueue,
1438 int srcIndex,
1439 int numElements)
1440{
1441 const int newLength = length() + numElements;
1442 const int minSize = calculateSufficientSize(newLength, d_size);
1443 if (d_size < minSize) {
1444 d_size = increaseSizeImp(&d_array_p,
1445 &d_front,
1446 &d_back,
1447 minSize,
1448 d_size,
1449 d_allocator_p);
1450 }
1451 d_back = memcpyCircular(d_array_p,
1452 d_size,
1453 d_back,
1454 srcQueue.d_array_p,
1455 srcQueue.d_size,
1456 (srcQueue.d_front + 1 + srcIndex) %
1457 srcQueue.d_size,
1458 numElements);
1459}
1460
1461template <class T>
1462inline
1464{
1465 return d_array_p[(d_back - 1 + d_size) % d_size];
1466}
1467
1468template <class T>
1469inline
1471{
1472 return d_array_p[(d_front + 1) % d_size];
1473}
1474
1475template <class T>
1476void Queue<T>::insert(int dstIndex, const T& item)
1477{
1478 T itemCopy(item); // TBD hack for aliased case
1479
1480 // The capacity must always be greater than or equal to
1481 // 'length + k_EXTRA_CAPACITY'.
1482
1483 const int originalLength = length();
1484 const int newLength = originalLength + 1;
1485 const int newSize = calculateSufficientSize(newLength, d_size);
1486
1487 if (d_size < newSize) {
1488 // resize, makes move easy
1489
1490 T *array = (T *)d_allocator_p->allocate(newSize * sizeof *d_array_p);
1491
1492 // COMMIT
1493
1494 const int start = d_front + 1;
1495
1496 // NOTE: newSize >= size + 1 so '% newSize' is not needed in next line.
1497
1498 memcpyCircular(array,
1499 newSize,
1500 start, // no '% newSize'
1501 d_array_p,
1502 d_size,
1503 start % d_size,
1504 dstIndex);
1505 memcpyCircular(array,
1506 newSize,
1507 (start + dstIndex + 1) % newSize,
1508 d_array_p,
1509 d_size,
1510 (start + dstIndex) % d_size,
1511 originalLength - dstIndex);
1512
1513 // TBD efficiency
1514
1515 for (int i = (d_front + 1) % d_size; i != d_back;
1516 i = (i + 1) % d_size) {
1517 d_array_p[i].~T();
1518 }
1519
1520 d_allocator_p->deallocate(d_array_p);
1521 d_array_p = array;
1522
1523 d_size = newSize;
1524 d_back = (start + newLength) % d_size;
1525 new (&d_array_p[(start + dstIndex) % d_size]) T(itemCopy);
1526 }
1527 else { // sufficient capacity
1528
1529 // No resize is required. Copy as few elements as possible.
1530
1531 // Compute number of elements that are past the insertion point: the
1532 // back length.
1533
1534 const int backLen = originalLength - dstIndex;
1535
1536 if (dstIndex < backLen) {
1537
1538 // We will choose to shift 'dstIndex' elements to the left.
1539
1540 const int src = (d_front + 1) % d_size;
1541 const int dst = d_front;
1542
1543 memShiftLeft(d_array_p, d_size, dst, src, dstIndex);
1544 new (&d_array_p[(d_front + dstIndex) % d_size]) T(itemCopy);
1545 d_front = (d_front - 1 + d_size) % d_size;
1546 }
1547 else {
1548
1549 // We will choose to shift 'backLen' elements to the right.
1550
1551 const int src = (d_front + 1 + dstIndex) % d_size;
1552 const int dst = (src + 1) % d_size;
1553
1554 memShiftRight(d_array_p,
1555 d_size,
1556 dst,
1557 src,
1558 backLen);
1559 new (&d_array_p[(d_front + 1 + dstIndex) % d_size]) T(itemCopy);
1560 d_back = (d_back + 1) % d_size;
1561 }
1562 }
1563}
1564
1565template <class T>
1566void Queue<T>::insert(int dstIndex,
1567 const Queue& srcQueue,
1568 int srcIndex,
1569 int numElements)
1570{
1571 // The capacity must always be greater than or equal to
1572 // 'length + k_EXTRA_CAPACITY'.
1573
1574 const int originalLength = length();
1575 const int newLength = originalLength + numElements;
1576 const int newSize = calculateSufficientSize(newLength, d_size);
1577
1578 if (d_size < newSize) {
1579 // resize, makes move easy
1580
1581 T *array = (T *)d_allocator_p->allocate(newSize * sizeof *d_array_p);
1582
1583 // COMMIT
1584
1585 const int start = d_front + 1;
1586 const int startIndex = start + dstIndex;
1587
1588 // NOTE: newSize >= size + 1 so '% newSize' is not needed in next line.
1589
1590 memcpyCircular(array,
1591 newSize,
1592 start, // no '% newSize'
1593 d_array_p,
1594 d_size,
1595 start % d_size,
1596 dstIndex);
1597 memcpyCircular(array,
1598 newSize,
1599 (startIndex + numElements) % newSize,
1600 d_array_p,
1601 d_size,
1602 (startIndex) % d_size,
1603 originalLength - dstIndex);
1604 memcpyCircular(array,
1605 newSize,
1606 startIndex % newSize,
1607 srcQueue.d_array_p,
1608 srcQueue.d_size,
1609 (srcQueue.d_front + 1 + srcIndex) % srcQueue.d_size,
1610 numElements);
1611
1612 // TBD efficiency
1613
1614 for (int i = (d_front + 1) % d_size; i != d_back;
1615 i = (i + 1) % d_size) {
1616 d_array_p[i].~T();
1617 }
1618
1619 d_allocator_p->deallocate(d_array_p);
1620 d_array_p = array;
1621 d_size = newSize;
1622 d_back = (start + newLength) % d_size;
1623 }
1624 else { // sufficient capacity
1625
1626 // No resize is required. Copy as few elements as possible.
1627
1628 // Compute number of elements that are past the insertion point: the
1629 // back length.
1630
1631 const int backLen = originalLength - dstIndex;
1632 if (dstIndex < backLen) {
1633
1634 // We will shift 'dstIndex' elements to the left.
1635
1636 const int d = (d_front + 1 - numElements + d_size) % d_size;
1637 memShiftLeft(d_array_p,
1638 d_size,
1639 d,
1640 (d_front + 1) % d_size,
1641 dstIndex);
1642
1643 if (this != &srcQueue || srcIndex >= dstIndex) { // not aliased
1644 memcpyCircular(d_array_p,
1645 d_size,
1646 (d + dstIndex) % d_size,
1647 srcQueue.d_array_p,
1648 srcQueue.d_size,
1649 (srcQueue.d_front + 1 + srcIndex) %
1650 srcQueue.d_size,
1651 numElements);
1652 }
1653 else { // aliased
1654 const int distance = dstIndex - srcIndex;
1655 if (distance >= numElements) {
1656 memcpyCircular(d_array_p,
1657 d_size,
1658 (d + dstIndex) % d_size,
1659 d_array_p,
1660 d_size,
1661 (d + srcIndex) % d_size,
1662 numElements);
1663 }
1664 else {
1665 memcpyCircular(d_array_p,
1666 d_size,
1667 (d + dstIndex) % d_size,
1668 d_array_p,
1669 d_size,
1670 (d + srcIndex) % d_size,
1671 distance);
1672 memcpyCircular(d_array_p,
1673 d_size,
1674 (d + dstIndex + distance) % d_size,
1675 d_array_p,
1676 d_size,
1677 (d_front + 1 + dstIndex) % d_size,
1678 numElements - distance);
1679 }
1680 }
1681 d_front = (d_front - numElements + d_size) % d_size;
1682 }
1683 else {
1684
1685 // We will shift 'backLen' elements to the right.
1686
1687 // Destination index is as close or closer to the back as to the
1688 // front.
1689
1690 const int s = (d_front + 1 + dstIndex) % d_size;
1691 memShiftRight(d_array_p,
1692 d_size,
1693 (s + numElements) % d_size,
1694 s,
1695 backLen);
1696
1697 if (this != &srcQueue ||
1698 srcIndex + numElements <= dstIndex) { // not aliased
1699 memcpyCircular(d_array_p,
1700 d_size,
1701 s,
1702 srcQueue.d_array_p,
1703 srcQueue.d_size,
1704 (srcQueue.d_front + 1 + srcIndex) %
1705 srcQueue.d_size,
1706 numElements);
1707 }
1708 else { // aliased
1709 if (dstIndex <= srcIndex) {
1710 memcpyCircular(d_array_p,
1711 d_size,
1712 s,
1713 d_array_p,
1714 d_size,
1715 (d_front + 1 + srcIndex + numElements) %
1716 d_size,
1717 numElements);
1718 }
1719 else {
1720 const int distance = dstIndex - srcIndex;
1721 memcpyCircular(d_array_p,
1722 d_size,
1723 s,
1724 d_array_p,
1725 d_size,
1726 (d_front + 1 + srcIndex) % d_size,
1727 distance);
1728 memcpyCircular(d_array_p,
1729 d_size,
1730 (s + distance) % d_size,
1731 d_array_p,
1732 d_size,
1733 (d_front + 1 + srcIndex + distance +
1734 numElements) % d_size,
1735 numElements - distance);
1736 }
1737 }
1738 d_back = (d_back + numElements) % d_size;
1739 }
1740 }
1741}
1742
1743template <class T>
1744inline
1745void Queue<T>::insert(int dstIndex, const Queue& srcQueue)
1746{
1747 insert(dstIndex, srcQueue, 0, srcQueue.length());
1748}
1749
1750template <class T>
1751inline
1753{
1754 d_back = (d_back - 1 + d_size) % d_size;
1755 d_array_p[d_back].~T();
1756}
1757
1758template <class T>
1759inline
1761{
1762 d_front = (d_front + 1) % d_size;
1763 d_array_p[d_front].~T();
1764}
1765
1766template <class T>
1767void Queue<T>::pushBack(const T& item)
1768{
1769 T itemCopy(item); // TBD aliasing hack
1770
1771 int newBack = (d_back + 1) % d_size;
1772 if (d_front == newBack) {
1773 increaseSize(); // NOTE: this can change the value of d_back
1774 newBack = (d_back + 1) % d_size;
1775 }
1776 new (&d_array_p[d_back]) T(itemCopy);
1777 d_back = newBack;
1778}
1779
1780template <class T>
1781void Queue<T>::pushFront(const T& item)
1782{
1783 T itemCopy(item); // TBD aliasing hack
1784
1785 int newFront = (d_front - 1 + d_size) % d_size;
1786 if (newFront == d_back) {
1787 increaseSize(); // NOTE: this can change the value of d_front
1788 newFront = (d_front - 1 + d_size) % d_size;
1789 }
1790 new (&d_array_p[d_front]) T(itemCopy);
1791 d_front = newFront;
1792}
1793
1794template <class T>
1795inline
1796void Queue<T>::append(const T& item)
1797{
1798 pushBack(item);
1799}
1800
1801template <class T>
1802void Queue<T>::remove(int index)
1803{
1804 d_array_p[(index + d_front + 1) % d_size].~T();
1805
1806 // Compute number of elements that are past the insertion point: the back
1807 // length.
1808
1809 const int backLen =
1810 (d_back - d_front - k_EXTRA_CAPACITY - index + d_size) % d_size;
1811
1812 if (index < backLen) {
1813 d_front = (d_front + 1) % d_size;
1814 memShiftRight(d_array_p,
1815 d_size,
1816 (d_front + 1) % d_size,
1817 d_front,
1818 index);
1819 }
1820 else {
1821 const int d = (d_front + 1 + index) % d_size;
1822 memShiftLeft(d_array_p,
1823 d_size,
1824 d,
1825 (d + 1) % d_size,
1826 (d_back + d_size - d_front - 1) % d_size - 1 - index);
1827 d_back = (d_back - 1 + d_size) % d_size;
1828 }
1829}
1830
1831template <class T>
1832void Queue<T>::remove(int index, int numElements)
1833{
1834 // TBD efficiency
1835
1836 for (int i = 0; i < numElements; ++i) {
1837 d_array_p[(index + d_front + 1 + i) % d_size].~T();
1838 }
1839
1840 // Compute number of elements that are past the insertion point: the back
1841 // length.
1842
1843 const int backLen = (d_back - d_front - 1
1844 - index - numElements + d_size) % d_size;
1845 if (index < backLen) {
1846 const int dst = (d_front + 1 + numElements) % d_size;
1847 const int src = (d_front + 1) % d_size;
1848
1849 memShiftRight(d_array_p, d_size, dst, src, index);
1850 d_front = (d_front + numElements) % d_size;
1851 }
1852 else {
1853 const int dst = (d_front + 1 + index) % d_size;
1854 const int src = (dst + numElements) % d_size;
1855
1856 memShiftLeft(d_array_p,
1857 d_size,
1858 dst,
1859 src,
1860 (d_back + d_size - d_front - 1) % d_size -
1861 numElements - index);
1862 d_back = (d_back - numElements + d_size) % d_size;
1863 }
1864}
1865
1866template <class T>
1868{
1869 d_front = (d_front + 1) % d_size;
1870
1871 // TBD efficiency
1872
1873 if (buffer) {
1874 while (d_back != d_front) {
1875 buffer->push_back(d_array_p[d_front]);
1876 d_array_p[d_front].~T();
1877 d_front = (d_front + 1) % d_size;
1878 }
1879 } else {
1880 while (d_back != d_front) {
1881 d_array_p[d_front].~T();
1882 d_front = (d_front + 1) % d_size;
1883 }
1884 }
1885 d_front = (d_back - 1 + d_size) % d_size;
1886}
1887
1888template <class T>
1889void Queue<T>::replace(int dstIndex, const T& item)
1890{
1891 T itemCopy(item); // TBD hack for aliased case
1892
1893 // TBD efficiency
1894
1895 d_array_p[(d_front + 1 + dstIndex) % d_size].~T();
1896 new (&d_array_p[(d_front + 1 + dstIndex) % d_size]) T(itemCopy);
1897}
1898
1899template <class T>
1900void Queue<T>::replace(int dstIndex,
1901 const Queue& srcQueue,
1902 int srcIndex,
1903 int numElements)
1904{
1905 // TBD need placement new
1906
1907 if (this != &srcQueue || srcIndex + numElements <= dstIndex ||
1908 dstIndex + numElements <= srcIndex) { // not aliased
1909 memcpyCircular(d_array_p,
1910 d_size,
1911 (d_front + 1 + dstIndex) % d_size,
1912 srcQueue.d_array_p,
1913 srcQueue.d_size,
1914 (srcQueue.d_front + 1 + srcIndex) % srcQueue.d_size,
1915 numElements);
1916 }
1917 else { // aliased; do nothing if srcIndex == dstIndex
1918 if (srcIndex < dstIndex) {
1919 memShiftRight(d_array_p,
1920 d_size,
1921 (d_front + 1 + dstIndex) % d_size,
1922 (d_front + 1 + srcIndex) % d_size,
1923 numElements);
1924 }
1925 else if (srcIndex > dstIndex) {
1926 memShiftLeft(d_array_p,
1927 d_size,
1928 (d_front + 1 + dstIndex) % d_size,
1929 (d_front + 1 + srcIndex) % d_size,
1930 numElements);
1931 }
1932 }
1933}
1934
1935template <class T>
1936void Queue<T>::reserveCapacity(int numElements)
1937{
1938 const int newSize = calculateSufficientSize(numElements, d_size);
1939 if (d_size < newSize) {
1940 d_size = increaseSizeImp(&d_array_p,
1941 &d_front,
1942 &d_back,
1943 newSize,
1944 d_size,
1945 d_allocator_p);
1946
1947 // To improve testability, all empty queues have canonical front and
1948 // back values.
1949
1950 if (0 == length()) {
1951 d_front = d_size - 1;
1952 d_back = 0;
1953 }
1954 }
1955}
1956
1957template <class T>
1958void Queue<T>::reserveCapacityRaw(int numElements)
1959{
1960 const int newSize = numElements + k_EXTRA_CAPACITY;
1961 // to hold the front/back positions
1962
1963 if (d_size < newSize) {
1964 d_size = increaseSizeImp(&d_array_p,
1965 &d_front,
1966 &d_back,
1967 newSize,
1968 d_size,
1969 d_allocator_p);
1970 }
1971}
1972
1973template <class T>
1974void Queue<T>::setLength(int newLength)
1975{
1976 const int newSize = newLength + k_EXTRA_CAPACITY;
1977 // to hold the front/back positions
1978
1979 if (d_size < newSize) {
1980 d_size = increaseSizeImp(&d_array_p,
1981 &d_front,
1982 &d_back,
1983 newSize,
1984 d_size,
1985 d_allocator_p);
1986 }
1987 const int oldBack = d_back;
1988 const int oldLength = length();
1989 d_back = (d_front + 1 + newLength) % d_size;
1990 if (newLength > oldLength) {
1991 if (oldBack < d_back) {
1992 // TBD efficiency
1993
1994 for (int i = 0; i < d_back - oldBack; ++i) {
1995 new (d_array_p + oldBack + i) T();
1996 }
1997 }
1998 else {
1999 // TBD efficiency
2000
2001 for (int i = 0; i < d_size - oldBack; ++i) {
2002 new (d_array_p + oldBack + i) T();
2003 }
2004
2005 // TBD efficiency
2006
2007 for (int i = 0; i < d_back; ++i) {
2008 new (d_array_p + i) T();
2009 }
2010 }
2011 }
2012}
2013
2014template <class T>
2015void Queue<T>::setLength(int newLength, const T& initialValue)
2016{
2017 const int newSize = newLength + k_EXTRA_CAPACITY;
2018 // to hold the empty positions
2019
2020 if (d_size < newSize) {
2021 d_size = increaseSizeImp(&d_array_p,
2022 &d_front,
2023 &d_back,
2024 newSize,
2025 d_size,
2026 d_allocator_p);
2027 }
2028 const int oldBack = d_back;
2029 const int oldLength = length();
2030 d_back = (d_front + 1 + newLength) % d_size;
2031 if (newLength > oldLength) {
2032 if (oldBack < d_back) {
2033 // TBD efficiency
2034
2035 for (int i = 0; i < d_back - oldBack; ++i) {
2036 new (d_array_p + oldBack + i) T(initialValue);
2037 }
2038 }
2039 else {
2040 // TBD efficiency
2041
2042 for (int i = 0; i < d_size - oldBack; ++i) {
2043 new (d_array_p + oldBack + i) T(initialValue);
2044 }
2045 // TBD efficiency
2046
2047 for (int i = 0; i < d_back; ++i) {
2048 new (d_array_p + i) T(initialValue);
2049 }
2050 }
2051 }
2052}
2053
2054template <class T>
2055void Queue<T>::setLengthRaw(int newLength)
2056{
2057 const int newSize = newLength + k_EXTRA_CAPACITY;
2058 // to hold the empty positions
2059
2060 if (d_size < newSize) {
2061 d_size = increaseSizeImp(&d_array_p,
2062 &d_front,
2063 &d_back,
2064 newSize,
2065 d_size,
2066 d_allocator_p);
2067 }
2068 d_back = (d_front + 1 + newLength) % d_size;
2069}
2070
2071template <class T>
2072template <class STREAM>
2073STREAM& Queue<T>::bdexStreamIn(STREAM& stream, int version)
2074{
2075 if (stream) {
2076 switch (version) { // switch on the schema version
2077 case 1: {
2078 int newLength;
2079 stream.getLength(newLength);
2080
2081 if (stream) {
2082 int newSize = calculateSufficientSize(newLength, d_size);
2083 if (d_size < newSize) {
2084 d_size = increaseSizeImp(&d_array_p,
2085 &d_front,
2086 &d_back,
2087 newSize,
2088 d_size,
2089 d_allocator_p);
2090 }
2091 d_front = d_size - 1;
2092 d_back = newLength;
2093 for (int i = 0; i < newLength && stream; ++i) {
2095 stream, (*this)[i], version);
2096 }
2097 }
2098 } break;
2099 default: {
2100 stream.invalidate(); // unrecognized version number
2101 }
2102 }
2103 }
2104 return stream;
2105}
2106
2107template <class T>
2108void Queue<T>::swap(int index1, int index2)
2109{
2110 if (index1 != index2) {
2111 const int tmp = d_front + 1;
2112 const int i1 = (tmp + index1) % d_size;
2113 const int i2 = (tmp + index2) % d_size;
2114
2115 T temp(d_array_p[i1]);
2116 d_array_p[i1].~T();
2117 new (d_array_p + i1) T(d_array_p[i2]);
2118 d_array_p[i2].~T();
2119 new (d_array_p + i2) T(temp);
2120 }
2121}
2122
2123// ACCESSORS
2124template <class T>
2125inline
2126const T& Queue<T>::operator[](int index) const
2127{
2128 return d_array_p[(index + d_front + 1) % d_size];
2129}
2130
2131template <class T>
2132inline
2133const T& Queue<T>::back() const
2134{
2135 return d_array_p[(d_back - 1 + d_size) % d_size];
2136}
2137
2138template <class T>
2139inline
2140const T& Queue<T>::front() const
2141{
2142 return d_array_p[(d_front + 1) % d_size];
2143}
2144
2145template <class T>
2146bsl::ostream& Queue<T>::print(bsl::ostream& stream,
2147 int level,
2148 int spacesPerLevel) const
2149{
2150 if (level < 0) {
2151 level = -level;
2152 }
2153 else {
2154 bdlb::Print::indent(stream, level, spacesPerLevel);
2155 }
2156
2157 int levelPlus1 = level + 1;
2158 if (0 <= spacesPerLevel) {
2159
2160 stream << "[\n";
2161
2162 const int len = length();
2163 for (int i = 0; i < len; ++i) {
2164 bdlb::Print::indent(stream, levelPlus1, spacesPerLevel);
2165 stream << d_array_p[(i + d_front + 1) % d_size] << '\n';
2166 }
2167
2168 bdlb::Print::indent(stream, level, spacesPerLevel);
2169 stream << "]\n";
2170 }
2171 else {
2172 stream << "[ ";
2173
2174 const int len = length();
2175 for (int i = 0; i < len; ++i) {
2176 stream << ' ';
2177 stream << d_array_p[(i + d_front + 1) % d_size];
2178 }
2179
2180 stream << " ] ";
2181 }
2182 return stream << bsl::flush;
2183}
2184
2185template <class T>
2186template <class STREAM>
2187STREAM& Queue<T>::bdexStreamOut(STREAM& stream, int version) const
2188{
2189 if (stream) {
2190 switch (version) { // switch on the schema version
2191 case 1: {
2192 const int len = length();
2193 stream.putLength(len);
2194 for (int i = 0; i < len && stream; ++i) {
2196 stream, (*this)[i], version);
2197 }
2198 } break;
2199 default: {
2200 stream.invalidate(); // unrecognized version number
2201 }
2202 }
2203 }
2204 return stream;
2205}
2206
2207} // close package namespace
2208
2209// FREE OPERATORS
2210template <class T>
2211bool bdlc::operator==(const Queue<T>& lhs, const Queue<T>& rhs)
2212{
2213 const int len = lhs.length();
2214 if (rhs.length() != len) {
2215 return 0; // RETURN
2216 }
2217
2218 // Lengths are equal.
2219
2220 for (int i = 0; i < len; ++i) {
2221 if (!(lhs[i] == rhs[i])) {
2222 return 0; // RETURN
2223 }
2224 }
2225 return 1;
2226}
2227
2228template <class T>
2229inline
2230bool bdlc::operator!=(const Queue<T>& lhs, const Queue<T>& rhs)
2231{
2232 return !(lhs == rhs);
2233}
2234
2235template <class T>
2236inline
2237bsl::ostream& bdlc::operator<<(bsl::ostream& stream, const Queue<T>& queue)
2238{
2239 return queue.streamOut(stream);
2240}
2241
2242
2243
2244#endif
2245
2246// ----------------------------------------------------------------------------
2247// Copyright 2018 Bloomberg Finance L.P.
2248//
2249// Licensed under the Apache License, Version 2.0 (the "License");
2250// you may not use this file except in compliance with the License.
2251// You may obtain a copy of the License at
2252//
2253// http://www.apache.org/licenses/LICENSE-2.0
2254//
2255// Unless required by applicable law or agreed to in writing, software
2256// distributed under the License is distributed on an "AS IS" BASIS,
2257// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2258// See the License for the specific language governing permissions and
2259// limitations under the License.
2260// ----------------------------- END-OF-FILE ----------------------------------
2261
2262/** @} */
2263/** @} */
2264/** @} */
Definition bdlc_queue.h:274
Queue(int initialLength, const T &initialValue, bslma::Allocator *basicAllocator=0)
Definition bdlc_queue.h:1288
BSLMF_NESTED_TRAIT_DECLARATION(Queue, bdlb::HasPrintMethod)
void append(const Queue &srcQueue)
Definition bdlc_queue.h:1414
void insert(int dstIndex, const Queue &srcQueue, int srcIndex, int numElements)
Definition bdlc_queue.h:1566
Queue(bslma::Allocator *basicAllocator=0)
Definition bdlc_queue.h:1260
const T & operator[](int index) const
Definition bdlc_queue.h:2126
static int maxSupportedVersion()
Definition bdlc_queue.h:1244
Queue(const InitialCapacity &numElements, bslma::Allocator *basicAllocator=0)
Definition bdlc_queue.h:1307
void setLength(int newLength)
Definition bdlc_queue.h:1974
const T & front() const
Definition bdlc_queue.h:2140
Queue(unsigned int initialLength, bslma::Allocator *basicAllocator=0)
Definition bdlc_queue.h:1270
void popFront()
Definition bdlc_queue.h:1760
void append(const Queue &srcQueue, int srcIndex, int numElements)
Definition bdlc_queue.h:1437
void replace(int dstIndex, const T &item)
Definition bdlc_queue.h:1889
void swap(int index1, int index2)
Definition bdlc_queue.h:2108
bsl::ostream & print(bsl::ostream &stream, int level, int spacesPerLevel) const
Definition bdlc_queue.h:2146
void setLengthRaw(int newLength)
Definition bdlc_queue.h:2055
static int maxSupportedBdexVersion()
Definition bdlc_queue.h:1251
void remove(int index)
Definition bdlc_queue.h:1802
static int maxSupportedBdexVersion(int versionSelector)
Definition bdlc_queue.h:1233
T & operator[](int index)
Definition bdlc_queue.h:1408
void pushBack(const T &item)
Definition bdlc_queue.h:1767
BSLMF_NESTED_TRAIT_DECLARATION(Queue, bslma::UsesBslmaAllocator)
Queue(const Queue &original, bslma::Allocator *basicAllocator=0)
Definition bdlc_queue.h:1336
Queue & operator=(const Queue &rhs)
Definition bdlc_queue.h:1366
bsl::ostream & streamOut(bsl::ostream &stream) const
Definition bdlc_queue.h:807
void remove(int index, int numElements)
Definition bdlc_queue.h:1832
void popBack()
Definition bdlc_queue.h:1752
T & front()
Definition bdlc_queue.h:1470
~Queue()
Destroy this object.
Definition bdlc_queue.h:1353
STREAM & bdexStreamIn(STREAM &stream, int version)
Definition bdlc_queue.h:2073
void setLength(int newLength, const T &initialValue)
Definition bdlc_queue.h:2015
void insert(int dstIndex, const T &item)
Definition bdlc_queue.h:1476
void reserveCapacity(int numElements)
Definition bdlc_queue.h:1936
void replace(int dstIndex, const Queue &srcQueue, int srcIndex, int numElements)
Definition bdlc_queue.h:1900
Queue(const T *srcArray, int numElements, bslma::Allocator *basicAllocator=0)
Definition bdlc_queue.h:1318
int length() const
Return the number of elements in this queue.
Definition bdlc_queue.h:882
void reserveCapacityRaw(int numElements)
Definition bdlc_queue.h:1958
void pushFront(const T &item)
Definition bdlc_queue.h:1781
const T & back() const
Definition bdlc_queue.h:2133
void append(const T &item)
Definition bdlc_queue.h:1796
void removeAll(bsl::vector< T > *buffer=0)
Definition bdlc_queue.h:1867
T & back()
Definition bdlc_queue.h:1463
void insert(int dstIndex, const Queue &srcQueue)
Definition bdlc_queue.h:1745
STREAM & bdexStreamOut(STREAM &stream, int version) const
Definition bdlc_queue.h:2187
Definition bslstl_vector.h:1120
void push_back(const VALUE_TYPE &value)
Definition bslstl_vector.h:4343
Definition bslma_allocator.h:545
virtual void deallocate(void *address)=0
virtual void * allocate(size_type size)=0
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
bsl::size_t size(const TYPE &array)
Return the number of elements in the specified array.
Definition bdlc_bitarray.h:506
bool operator==(const BitArray &lhs, const BitArray &rhs)
bool operator!=(const BitArray &lhs, const BitArray &rhs)
BitArray operator<<(const BitArray &array, bsl::size_t numBits)
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
STREAM & bdexStreamIn(STREAM &stream, VALUE_TYPE &variable)
Definition bslx_instreamfunctions.h:1263
STREAM & bdexStreamOut(STREAM &stream, const TYPE &value)
Definition bslx_outstreamfunctions.h:1004
Definition bdlb_printmethods.h:306
static bsl::ostream & indent(bsl::ostream &stream, int level, int spacesPerLevel=4)
Definition bdlc_queue.h:298
InitialCapacity(unsigned int i)
Definition bdlc_queue.h:303
unsigned int d_i
Definition bdlc_queue.h:300
~InitialCapacity()
Definition bdlc_queue.h:304
Definition bslma_usesbslmaallocator.h:344