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