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