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