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