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