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