dynamic_vector_impl.h revision 37f8ef3069cfd12ced355a99c372f97cb9cf1363
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_IMPL_H_
18#define CHRE_UTIL_DYNAMIC_VECTOR_IMPL_H_
19
20#include "chre/util/dynamic_vector.h"
21
22#include <memory>
23#include <new>
24#include <utility>
25
26#include "chre/util/container_support.h"
27#include "chre/util/memory.h"
28
29namespace chre {
30
31template<typename ElementType>
32DynamicVector<ElementType>::DynamicVector() {}
33
34template<typename ElementType>
35DynamicVector<ElementType>::DynamicVector(DynamicVector<ElementType>&& other)
36    : mData(other.mData),
37      mSize(other.mSize),
38      mCapacity(other.mCapacity),
39      mDataIsWrapped(other.mDataIsWrapped) {
40  other.mData = nullptr;
41  other.mSize = 0;
42  other.mCapacity = 0;
43  other.mDataIsWrapped = false;
44}
45
46template<typename ElementType>
47DynamicVector<ElementType>::~DynamicVector() {
48  if (owns_data()) {
49    clear();
50    memoryFree(mData);
51  }
52}
53
54template<typename ElementType>
55DynamicVector<ElementType>& DynamicVector<ElementType>::operator=(
56    DynamicVector<ElementType>&& other) {
57  if (this == &other) {
58    return *this;
59  }
60  this->~DynamicVector();
61
62  mData = other.mData;
63  mSize = other.mSize;
64  mCapacity = other.mCapacity;
65  mDataIsWrapped = other.mDataIsWrapped;
66
67  other.mData = nullptr;
68  other.mSize = 0;
69  other.mCapacity = 0;
70  other.mDataIsWrapped = false;
71  return *this;
72}
73
74template <typename ElementType>
75void DynamicVector<ElementType>::clear() {
76  destroy(mData, mSize);
77  mSize = 0;
78}
79
80template<typename ElementType>
81ElementType *DynamicVector<ElementType>::data() {
82  return mData;
83}
84
85template<typename ElementType>
86const ElementType *DynamicVector<ElementType>::data() const {
87  return mData;
88}
89
90template<typename ElementType>
91typename DynamicVector<ElementType>::size_type
92    DynamicVector<ElementType>::size() const {
93  return mSize;
94}
95
96template<typename ElementType>
97typename DynamicVector<ElementType>::size_type
98    DynamicVector<ElementType>::capacity() const {
99  return mCapacity;
100}
101
102template<typename ElementType>
103bool DynamicVector<ElementType>::empty() const {
104  return (mSize == 0);
105}
106
107template<typename ElementType>
108void DynamicVector<ElementType>::pop_back() {
109  CHRE_ASSERT(!empty());
110  erase(mSize - 1);
111}
112
113template<typename ElementType>
114bool DynamicVector<ElementType>::push_back(const ElementType& element) {
115  bool spaceAvailable = prepareForPush();
116  if (spaceAvailable) {
117    new (&mData[mSize++]) ElementType(element);
118  }
119
120  return spaceAvailable;
121}
122
123template<typename ElementType>
124bool DynamicVector<ElementType>::push_back(ElementType&& element) {
125  bool spaceAvailable = prepareForPush();
126  if (spaceAvailable) {
127    new (&mData[mSize++]) ElementType(std::move(element));
128  }
129
130  return spaceAvailable;
131}
132
133template<typename ElementType>
134template<typename... Args>
135bool DynamicVector<ElementType>::emplace_back(Args&&... args) {
136  bool spaceAvailable = prepareForPush();
137  if (spaceAvailable) {
138    new (&data()[mSize++]) ElementType(std::forward<Args>(args)...);
139  }
140
141  return spaceAvailable;
142}
143
144template<typename ElementType>
145ElementType& DynamicVector<ElementType>::operator[](size_type index) {
146  CHRE_ASSERT(index < mSize);
147  return data()[index];
148}
149
150template<typename ElementType>
151const ElementType& DynamicVector<ElementType>::operator[](size_type index)
152    const {
153  CHRE_ASSERT(index < mSize);
154  return data()[index];
155}
156
157template<typename ElementType>
158bool DynamicVector<ElementType>::operator==(const DynamicVector<ElementType>& other)
159    const {
160  bool vectorsAreEqual = (mSize == other.mSize);
161  if (vectorsAreEqual) {
162    for (size_type i = 0; i < mSize; i++) {
163      if (!(mData[i] == other.mData[i])) {
164        vectorsAreEqual = false;
165        break;
166      }
167    }
168  }
169
170  return vectorsAreEqual;
171}
172
173template<typename ElementType>
174bool DynamicVector<ElementType>::reserve(size_type newCapacity) {
175  bool success = false;
176
177  CHRE_ASSERT(owns_data());
178  if (newCapacity <= mCapacity) {
179    success = true;
180  } else if (owns_data()) {
181    ElementType *newData = static_cast<ElementType *>(
182        memoryAlloc(newCapacity * sizeof(ElementType)));
183    if (newData != nullptr) {
184      uninitializedMoveOrCopy(mData, mSize, newData);
185      destroy(mData, mSize);
186      memoryFree(mData);
187      mData = newData;
188      mCapacity = newCapacity;
189      success = true;
190    }
191  }
192
193  return success;
194}
195
196template<typename ElementType>
197bool DynamicVector<ElementType>::insert(size_type index,
198                                        const ElementType& element) {
199  bool inserted = prepareInsert(index);
200  if (inserted) {
201    new (&mData[index]) ElementType(element);
202  }
203  return inserted;
204}
205
206template<typename ElementType>
207bool DynamicVector<ElementType>::insert(size_type index, ElementType&& element) {
208  bool inserted = prepareInsert(index);
209  if (inserted) {
210    new (&mData[index]) ElementType(std::move(element));
211  }
212  return inserted;
213}
214
215template<typename ElementType>
216bool DynamicVector<ElementType>::prepareInsert(size_type index) {
217  // Insertions are not allowed to create a sparse array.
218  CHRE_ASSERT(index <= mSize);
219
220  // TODO: this can be optimized in the case where we need to grow the vector to
221  // do the shift when transferring the values from the old array to the new.
222  bool readyForInsert = (index <= mSize && prepareForPush());
223  if (readyForInsert) {
224    // If we aren't simply appending the new object, create an opening where
225    // we'll insert it
226    if (index < mSize) {
227      // Make a duplicate of the last item in the slot where we're growing
228      uninitializedMoveOrCopy(&mData[mSize - 1], 1, &mData[mSize]);
229      // Shift all elements starting at index towards the end
230      for (size_type i = mSize - 1; i > index; i--) {
231        moveOrCopyAssign(mData[i], mData[i - 1]);
232      }
233
234      mData[index].~ElementType();
235    }
236
237    mSize++;
238  }
239
240  return readyForInsert;
241}
242
243template<typename ElementType>
244bool DynamicVector<ElementType>::copy_array(const ElementType *array,
245                                            size_type elementCount) {
246  CHRE_ASSERT(owns_data());
247
248  bool success = false;
249  if (owns_data() && reserve(elementCount)) {
250    clear();
251    std::copy(array, array + elementCount, mData);
252    mSize = elementCount;
253    success = true;
254  }
255
256  return success;
257}
258
259template<typename ElementType>
260void DynamicVector<ElementType>::erase(size_type index) {
261  CHRE_ASSERT(index < mSize);
262  mSize--;
263  for (size_type i = index; i < mSize; i++) {
264    moveOrCopyAssign(mData[i], mData[i + 1]);
265  }
266
267  mData[mSize].~ElementType();
268}
269
270template<typename ElementType>
271typename DynamicVector<ElementType>::size_type
272    DynamicVector<ElementType>::find(const ElementType& element) const {
273  // TODO: Consider adding iterator support and making this a free function.
274  size_type i;
275  for (i = 0; i < size(); i++) {
276    if (mData[i] == element) {
277      break;
278    }
279  }
280
281  return i;
282}
283
284template<typename ElementType>
285void DynamicVector<ElementType>::swap(size_type index0, size_type index1) {
286  CHRE_ASSERT(index0 < mSize && index1 < mSize);
287  if (index0 != index1) {
288    typename std::aligned_storage<sizeof(ElementType),
289        alignof(ElementType)>::type tempStorage;
290    ElementType& temp = *reinterpret_cast<ElementType *>(&tempStorage);
291    uninitializedMoveOrCopy(&mData[index0], 1, &temp);
292    moveOrCopyAssign(mData[index0], mData[index1]);
293    moveOrCopyAssign(mData[index1], temp);
294  }
295}
296
297template<typename ElementType>
298void DynamicVector<ElementType>::wrap(ElementType *array, size_type elementCount) {
299  // If array is nullptr, elementCount must also be 0
300  CHRE_ASSERT(array != nullptr || elementCount == 0);
301  this->~DynamicVector();
302
303  mData = array;
304  mSize = elementCount;
305  mCapacity = mSize;
306  mDataIsWrapped = true;
307}
308
309template<typename ElementType>
310void DynamicVector<ElementType>::unwrap() {
311  if (mDataIsWrapped) {
312    mData = nullptr;
313    mSize = 0;
314    mCapacity = 0;
315    mDataIsWrapped = false;
316  }
317}
318
319template<typename ElementType>
320bool DynamicVector<ElementType>::owns_data() const {
321  return !mDataIsWrapped;
322}
323
324template<typename ElementType>
325ElementType& DynamicVector<ElementType>::front() {
326  CHRE_ASSERT(mSize > 0);
327  return mData[0];
328}
329
330template<typename ElementType>
331const ElementType& DynamicVector<ElementType>::front() const {
332  CHRE_ASSERT(mSize > 0);
333  return mData[0];
334}
335
336template<typename ElementType>
337ElementType& DynamicVector<ElementType>::back() {
338  CHRE_ASSERT(mSize > 0);
339  return mData[mSize - 1];
340}
341
342template<typename ElementType>
343const ElementType& DynamicVector<ElementType>::back() const {
344  CHRE_ASSERT(mSize > 0);
345  return mData[mSize - 1];
346}
347
348template<typename ElementType>
349bool DynamicVector<ElementType>::prepareForPush() {
350  bool spaceAvailable = true;
351  if (mSize == mCapacity) {
352    size_type newCapacity = mCapacity * 2;
353    if (newCapacity == 0) {
354      newCapacity = 1;
355    }
356
357    if (!reserve(newCapacity)) {
358      spaceAvailable = false;
359    }
360  }
361
362  return spaceAvailable;
363}
364
365template<typename ElementType>
366typename DynamicVector<ElementType>::iterator
367    DynamicVector<ElementType>::begin() {
368  return mData;
369}
370
371template<typename ElementType>
372typename DynamicVector<ElementType>::iterator
373    DynamicVector<ElementType>::end() {
374  return (mData + mSize);
375}
376
377template<typename ElementType>
378typename DynamicVector<ElementType>::const_iterator
379    DynamicVector<ElementType>::begin() const {
380  return cbegin();
381}
382
383template<typename ElementType>
384typename DynamicVector<ElementType>::const_iterator
385    DynamicVector<ElementType>::end() const {
386  return cend();
387}
388
389template<typename ElementType>
390typename DynamicVector<ElementType>::const_iterator
391    DynamicVector<ElementType>::cbegin() const {
392  return mData;
393}
394
395template<typename ElementType>
396typename DynamicVector<ElementType>::const_iterator
397    DynamicVector<ElementType>::cend() const {
398  return (mData + mSize);
399}
400
401}  // namespace chre
402
403#endif  // CHRE_UTIL_DYNAMIC_VECTOR_IMPL_H_
404