Home | History | Annotate | Download | only in util
      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