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