• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
24 namespace chre {
25 
26 /**
27  * A container for storing a sequential array of elements. This container
28  * resizes dynamically using heap allocations.
29  */
30 template<typename ElementType>
31 class 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