dynamic_vector_impl.h revision 3fe2daaded2dc07da1175e3d5655d7dd956a0ba9
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 <utility> 21 22#include "chre/platform/assert.h" 23#include "chre/platform/memory.h" 24#include "chre/util/dynamic_vector.h" 25 26namespace chre { 27 28template<typename ElementType> 29DynamicVector<ElementType>::~DynamicVector() { 30 for (size_t i = 0; i < mSize; i++) { 31 mData[i].~ElementType(); 32 } 33 34 memoryFree(mData); 35} 36 37template<typename ElementType> 38ElementType *DynamicVector<ElementType>::data() { 39 return mData; 40} 41 42template<typename ElementType> 43const ElementType *DynamicVector<ElementType>::data() const { 44 return mData; 45} 46 47template<typename ElementType> 48size_t DynamicVector<ElementType>::size() const { 49 return mSize; 50} 51 52template<typename ElementType> 53size_t DynamicVector<ElementType>::capacity() const { 54 return mCapacity; 55} 56 57template<typename ElementType> 58bool DynamicVector<ElementType>::empty() const { 59 return (mSize == 0); 60} 61 62template<typename ElementType> 63bool DynamicVector<ElementType>::push_back(const ElementType& element) { 64 bool spaceAvailable = prepareForPush(); 65 if (spaceAvailable) { 66 mData[mSize++] = element; 67 } 68 69 return spaceAvailable; 70} 71 72template<typename ElementType> 73template<typename... Args> 74bool DynamicVector<ElementType>::emplace_back(Args&&... args) { 75 bool spaceAvailable = prepareForPush(); 76 if (spaceAvailable) { 77 new (&data()[mSize++]) ElementType(std::forward<Args>(args)...); 78 } 79 80 return spaceAvailable; 81} 82 83template<typename ElementType> 84ElementType& DynamicVector<ElementType>::operator[](size_t index) { 85 ASSERT(index < mSize); 86 if (index >= mSize) { 87 index = mSize - 1; 88 } 89 90 return data()[index]; 91} 92 93template<typename ElementType> 94const ElementType& DynamicVector<ElementType>::operator[](size_t index) const { 95 ASSERT(index < mSize); 96 if (index >= mSize) { 97 index = mSize - 1; 98 } 99 100 return data()[index]; 101} 102 103template<typename ElementType> 104bool DynamicVector<ElementType>::reserve(size_t newCapacity) { 105 // If the new capacity is less than or equal to the current capacitywe can 106 // avoid any memory allocation/deallocation/copying. 107 if (newCapacity <= mCapacity) { 108 return true; 109 } 110 111 ElementType *newData = static_cast<ElementType *>( 112 memoryAlloc(newCapacity * sizeof(ElementType))); 113 if (newData == nullptr) { 114 return false; 115 } 116 117 std::copy(mData, mData + mSize, newData); 118 memoryFree(mData); 119 mData = newData; 120 mCapacity = newCapacity; 121 return true; 122} 123 124template<typename ElementType> 125bool DynamicVector<ElementType>::insert(size_t index, 126 const ElementType& element) { 127 // Ensure that the user is not trying to insert an element after the 128 // contiguous block of elements. 129 if (index > mSize) { 130 return false; 131 } 132 133 // Allocate space if needed. 134 if (!prepareForPush()) { 135 return false; 136 } 137 138 // Shift all elements starting at the given index backward one position. 139 for (size_t i = mSize; i > index; i--) { 140 mData[i] = std::move(mData[i - 1]); 141 } 142 143 mData[index].~ElementType(); 144 145 // Insert the new element. 146 mData[index] = element; 147 mSize++; 148 return true; 149} 150 151template<typename ElementType> 152bool DynamicVector<ElementType>::prepareForPush() { 153 bool spaceAvailable = true; 154 if (mSize == mCapacity) { 155 size_t newCapacity = mCapacity * 2; 156 if (newCapacity == 0) { 157 newCapacity = 1; 158 } 159 160 if (!reserve(newCapacity)) { 161 spaceAvailable = false; 162 } 163 } 164 165 return spaceAvailable; 166} 167 168} // namespace chre 169 170#endif // CHRE_UTIL_DYNAMIC_VECTOR_IMPL_H_ 171