dynamic_vector.h revision 94928e4afa74f1ce137a7ccc243a6fb74d59abc3
1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef CHRE_UTIL_DYNAMIC_VECTOR_H_
18#define CHRE_UTIL_DYNAMIC_VECTOR_H_
19
20#include <cstddef>
21
22#include "chre/util/non_copyable.h"
23
24namespace chre {
25
26/**
27 * A container for storing a sequential array of elements. This container
28 * resizes dynamically using heap allocations.
29 */
30template<typename ElementType>
31class DynamicVector : public NonCopyable {
32 public:
33  /**
34   * Random-access iterator that points to some element in the container.
35   */
36  typedef ElementType* iterator;
37  typedef const ElementType* const_iterator;
38
39  typedef size_t size_type;
40
41  /**
42   * Default-constructs a dynamic vector.
43   */
44  DynamicVector();
45
46  /**
47   * Move-constructs a dynamic vector from another. The other dynamic vector is
48   * left in an empty state.
49   *
50   * @param other The other vector to move from.
51   */
52  DynamicVector(DynamicVector<ElementType>&& other);
53
54  /**
55   * Move-constructs a dynamic vector from another. The other dynamic vector is
56   * left in an empty state.
57   */
58  DynamicVector& operator=(DynamicVector<ElementType>&& other);
59
60  /**
61   * Destructs the objects and releases the memory owned by the vector.
62   */
63  ~DynamicVector();
64
65  /**
66   * Removes all elements from the vector, but does not change the capacity.
67   * All iterators and references are invalidated.
68   */
69  void clear();
70
71  /**
72   * Returns a pointer to the underlying buffer. Note that this should not be
73   * considered to be persistent as the vector will be moved and resized
74   * automatically.
75   *
76   * @return The pointer to the underlying buffer.
77   */
78  ElementType *data();
79
80  /**
81   * Returns a const pointer to the underlying buffer. Note that this should not
82   * be considered to be persistent as the vector will be moved and resized
83   * automatically.
84   *
85   * @return The const pointer to the underlying buffer.
86   */
87  const ElementType *data() const;
88
89  /**
90   * Returns the current number of elements in the vector.
91   *
92   * @return The number of elements in the vector.
93   */
94  size_type size() const;
95
96  /**
97   * Returns the maximum number of elements that can be stored in this vector
98   * without a resize operation.
99   *
100   * @return The capacity of the vector.
101   */
102  size_type capacity() const;
103
104  /**
105   * Determines whether the vector is empty or not.
106   *
107   * @return true if the vector is empty.
108   */
109  bool empty() const;
110
111  /**
112   * Erases the last element in the vector. Invalid to call on an empty vector.
113   *
114   * Invalidates any references to back() and end()/cend().
115   */
116  void pop_back();
117
118  /**
119   * Copy- or move-constructs an element onto the back of the vector. If the
120   * vector requires a resize and that allocation fails this function will
121   * return false. All iterators and references are invalidated if the container
122   * has been resized. Otherwise, only the past-the-end iterator is invalidated.
123   *
124   * @param The element to push onto the vector.
125   * @return true if the element was pushed successfully.
126   */
127  bool push_back(const ElementType& element);
128  bool push_back(ElementType&& element);
129
130  /**
131   * Constructs an element onto the back of the vector. All iterators and
132   * references are invalidated if the container has been resized. Otherwise,
133   * only the past-the-end iterator is invalidated.
134   *
135   * @param The arguments to the constructor
136   * @return true if the element is constructed successfully.
137   */
138  template<typename... Args>
139  bool emplace_back(Args&&... args);
140
141  /**
142   * Obtains an element of the vector given an index. It is illegal to index
143   * this vector out of bounds and the user of the API must check the size()
144   * function prior to indexing this vector to ensure that they will not read
145   * out of bounds.
146   *
147   * @param The index of the element.
148   * @return The element.
149   */
150  ElementType& operator[](size_type index);
151
152  /**
153   * Obtains a const element of the vector given an index. It is illegal to
154   * index this vector out of bounds and the user of the API must check the
155   * size() function prior to indexing this vector to ensure that they will not
156   * read out of bounds.
157   *
158   * @param The index of the element.
159   * @return The element.
160   */
161  const ElementType& operator[](size_type index) const;
162
163  /**
164   * Compares two vectors for equality. It will compare the vector sizes and
165   * return false if those are different; if not, it will compare the contents
166   * of the vectors element-by-element. The operator == should be defined and
167   * meaningful for the vector's element type.
168   *
169   * @param Right-hand side vector to compared with.
170   * @return true if two vectors are equal, false otherwise.
171   */
172  bool operator==(const DynamicVector<ElementType>& other) const;
173
174  /**
175   * Resizes the vector to a new capacity returning true if allocation was
176   * successful. If the new capacity is smaller than the current capacity,
177   * the operation is a no-op and true is returned. If a memory allocation
178   * fails, the contents of the vector are not modified and false is returned.
179   * This is intended to be similar to the reserve function of the std::vector.
180   * All iterators and references are invalidated unless the container did not
181   * resize.
182   *
183   * @param The new capacity of the vector.
184   * @return true if the resize operation was successful.
185   */
186  bool reserve(size_type newCapacity);
187
188  /**
189   * Resizes the vector to a new size. If the new capacity is smaller than the
190   * current size, the extraneous objects at the end are destructed. If the new
191   * capacity is larger than the current size, the new objects are
192   * default-constructed.
193   *
194   * @param size The new size of the vector.
195   * @return true if the resize operation was successful.
196   */
197  bool resize(size_type newSize);
198
199  /**
200   * Inserts an element into the vector at a given index. If a resize of the
201   * vector is required and the allocation fails, false will be returned. This
202   * will shift all vector elements after the given index one position backward
203   * in the list. The supplied index must be <= the size of the vector. It is
204   * not possible to have a sparse list of items. If the index is > the current
205   * size of the vector, false will be returned. All iterators and references
206   * to and after the indexed element are invalidated. Iterators and references
207   * to before the indexed elements are unaffected if the container did not resize.
208   *
209   * @param index The index to insert an element at.
210   * @param element The element to insert.
211   * @return Whether or not the insert operation was successful.
212   */
213  bool insert(size_type index, const ElementType& element);
214  bool insert(size_type index, ElementType&& element);
215
216  /**
217   * Similar to wrap(), except makes a copy of the supplied C-style array,
218   * maintaining ownership of the buffer within the DynamicVector container. The
219   * vector's capacity is increased if necessary to fit the given array, though
220   * note that this function will not cause the capacity to shrink. Upon
221   * successful reservation of necessary capacity, any pre-existing items in the
222   * vector are removed (via clear()), the supplied array is copied, and the
223   * vector's size is set to elementCount. All iterators and references are
224   * invalidated unless the container did not resize.
225   *
226   * This is essentially equivalent to calling these functions from std::vector:
227   *   vector.clear();
228   *   vector.insert(vector.begin(), array, &array[elementCount]);
229   *
230   * This function is not valid to call on a vector where owns_data() is false.
231   * Use unwrap() first in that case.
232   *
233   * @param array Pointer to the start of an array
234   * @param elementCount Number of elements in the supplied array to copy
235   *
236   * @return true if capacity was reserved to fit the supplied array (or the
237   *         vector already had sufficient capacity), and the supplied array was
238   *         copied into the vector. If false, the vector is not modified.
239   */
240  bool copy_array(const ElementType *array, size_type elementCount);
241
242  /**
243   * Removes an element from the vector given an index. All elements after the
244   * indexed one are moved forward one position. The destructor is invoked on
245   * on the invalid item left at the end of the vector. The index passed in
246   * must be less than the size() of the vector. If the index is greater than or
247   * equal to the size no operation is performed. All iterators and references
248   * to and after the indexed element are invalidated.
249   *
250   * @param index The index to remove an element at.
251   */
252  void erase(size_type index);
253
254  /**
255   * Searches the vector for an element.
256   *
257   * @param element The element to comare against.
258   * @return The index of the element found. If the return is equal to size()
259   *         then the element was not found.
260   */
261  size_type find(const ElementType& element) const;
262
263  /**
264   * Swaps the location of two elements stored in the vector. The indices
265   * passed in must be less than the size() of the vector. If the index is
266   * greater than or equal to the size, no operation is performed. All
267   * iterators and references to these two indexed elements are invalidated.
268   *
269   * @param index0 The index of the first element
270   * @param index1 The index of the second element
271   */
272  void swap(size_type index0, size_type index1);
273
274  /**
275   * Wraps an existing C-style array so it can be used as a DynamicVector. A
276   * reference to the supplied array is kept, as opposed to making a copy. The
277   * caller retains ownership of the memory. Calling code must therefore ensure
278   * that the lifetime of the supplied array is at least as long as that of this
279   * vector, and that the memory is released after this vector is destructed, as
280   * the vector will not attempt to free the memory itself.
281   *
282   * Once a vector wraps another buffer, it cannot be resized except through
283   * another call to wrap(). However, elements can be erased to make room for
284   * adding new elements.
285   *
286   * Destruction of elements within a wrapped array remains the responsibility
287   * of the calling code. While the vector may invoke the element destructor as
288   * a result of explicit calls to functions like erase() or clear(), it will
289   * not destruct elements remaining in the array when the vector is destructed.
290   * Therefore, special care must be taken when wrapping an array of elements
291   * that have a non-trivial destructor.
292   *
293   * @param array Pointer to a pre-allocated array
294   * @param elementCount Number of elements in the array (NOT the array's size
295   *        in bytes); will become the vector's size() and capacity()
296   */
297  void wrap(ElementType *array, size_type elementCount);
298
299
300  /**
301   * Returns a vector that is wrapping an array to the newly-constructed state,
302   * with capacity equal to 0, and owns_data() is true.
303   */
304  void unwrap();
305
306  /**
307   * @return false if this vector is wrapping an array passed in via wrap()
308   */
309  bool owns_data() const;
310
311  /**
312   * Returns a reference to the first element in the vector. It is illegal to
313   * call this on an empty vector.
314   *
315   * @return The first element in the vector.
316   */
317  ElementType& front();
318
319  /**
320   * Returns a const reference to the first element in the vector. It is illegal
321   * to call this on an empty vector.
322   *
323   * @return The first element in the vector.
324   */
325  const ElementType& front() const;
326
327  /**
328   * Returns a reference to the last element in the vector. It is illegal to
329   * call this on an empty vector.
330   *
331   * @return The last element in the vector.
332   */
333  ElementType& back();
334
335  /**
336   * Returns a const reference to the last element in the vector. It is illegal
337   * to call this on an empty vector.
338   *
339   * @return The last element in the vector.
340   */
341  const ElementType& back() const;
342
343  /**
344   * Prepares a vector to push a minimum of one element onto the back. The
345   * vector may be resized if required. The capacity of the vector increases
346   * with the growth policy of this vector (doubles for each resize for now).
347   *
348   * @return Whether or not the resize was successful.
349   */
350  bool prepareForPush();
351
352  /**
353   * @return A random-access iterator to the beginning.
354   */
355  typename DynamicVector<ElementType>::iterator begin();
356  typename DynamicVector<ElementType>::const_iterator begin() const;
357  typename DynamicVector<ElementType>::const_iterator cbegin() const;
358
359  /**
360   * @return A random-access iterator to the end.
361   */
362  typename DynamicVector<ElementType>::iterator end();
363  typename DynamicVector<ElementType>::const_iterator end() const;
364  typename DynamicVector<ElementType>::const_iterator cend() const;
365
366 private:
367  //! A pointer to the underlying data buffer.
368  ElementType *mData = nullptr;
369
370  //! The current size of the vector, as in the number of elements stored.
371  size_t mSize = 0;
372
373  //! The current capacity of the vector, as in the maximum number of elements
374  //! that can be stored.
375  size_t mCapacity = 0;
376
377  //! Set to true when the buffer (mData) was supplied via wrap()
378  bool mDataIsWrapped = false;
379
380  /**
381   * Prepares the vector for insertion - upon successful return, the memory at
382   * the given index will be allocated but uninitialized
383   *
384   * @param index
385   * @return true
386   */
387  bool prepareInsert(size_t index);
388};
389
390}  // namespace chre
391
392#include "chre/util/dynamic_vector_impl.h"
393
394#endif  // CHRE_UTIL_DYNAMIC_VECTOR_H_
395