void* VectorImpl::_grow(size_t where, size_t amount) { // ALOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d", // this, (int)where, (int)amount, (int)mCount, (int)capacity()); ALOG_ASSERT(where <= mCount, "[%p] _grow: where=%d, amount=%d, count=%d", this, (int)where, (int)amount, (int)mCount); // caller already checked const size_t new_size = mCount + amount; if (capacity() < new_size) { const size_t new_capacity = max(kMinVectorCapacity, ((new_size*3)+1)/2); // ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity); if ((mStorage) && (mCount==where) && (mFlags & HAS_TRIVIAL_COPY) && (mFlags & HAS_TRIVIAL_DTOR)) { const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage); SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize); if (sb) { mStorage = sb->data(); } else { return NULL; } } else { SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize); if (sb) { void* array = sb->data(); if (where != 0) { _do_copy(array, mStorage, where); } if (where != mCount) { const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize; void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; _do_copy(dest, from, mCount-where); } release_storage(); mStorage = const_cast<void*>(array); } else { return NULL; } } } else { void* array = editArrayImpl(); if (where != mCount) { const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize; void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; _do_move_forward(to, from, mCount - where); } } mCount = new_size; void* free_space = const_cast<void*>(itemLocation(where)); return free_space; }
ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector) { // we've merging a sorted vector... nice! ssize_t err = NO_ERROR; if (!vector.isEmpty()) { // first take care of the case where the vectors are sorted together if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) { err = VectorImpl::insertVectorAt(static_cast<const VectorImpl&>(vector), 0); } else if (do_compare(vector.arrayImpl(), itemLocation(size()-1)) >= 0) { err = VectorImpl::appendVector(static_cast<const VectorImpl&>(vector)); } else { // this could be made a little better err = merge(static_cast<const VectorImpl&>(vector)); } } return err; }
void* VectorImpl::_grow(size_t where, size_t amount) { // ALOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d", // this, (int)where, (int)amount, (int)mCount, (int)capacity()); ALOG_ASSERT(where <= mCount, "[%p] _grow: where=%d, amount=%d, count=%d", this, (int)where, (int)amount, (int)mCount); // caller already checked size_t new_size; LOG_ALWAYS_FATAL_IF(!safe_add(&new_size, mCount, amount), "new_size overflow"); if (capacity() < new_size) { // NOTE: This implementation used to resize vectors as per ((3*x + 1) / 2) // (sigh..). Also note, the " + 1" was necessary to handle the special case // where x == 1, where the resized_capacity will be equal to the old // capacity without the +1. The old calculation wouldn't work properly // if x was zero. // // This approximates the old calculation, using (x + (x/2) + 1) instead. size_t new_capacity = 0; LOG_ALWAYS_FATAL_IF(!safe_add(&new_capacity, new_size, (new_size / 2)), "new_capacity overflow"); LOG_ALWAYS_FATAL_IF(!safe_add(&new_capacity, new_capacity, static_cast<size_t>(1u)), "new_capacity overflow"); new_capacity = max(kMinVectorCapacity, new_capacity); size_t new_alloc_size = 0; LOG_ALWAYS_FATAL_IF(!safe_mul(&new_alloc_size, new_capacity, mItemSize), "new_alloc_size overflow"); // ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity); if ((mStorage) && (mCount==where) && (mFlags & HAS_TRIVIAL_COPY) && (mFlags & HAS_TRIVIAL_DTOR)) { const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage); SharedBuffer* sb = cur_sb->editResize(new_alloc_size); if (sb) { mStorage = sb->data(); } else { return NULL; } } else { SharedBuffer* sb = SharedBuffer::alloc(new_alloc_size); if (sb) { void* array = sb->data(); if (where != 0) { _do_copy(array, mStorage, where); } if (where != mCount) { const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize; void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; _do_copy(dest, from, mCount-where); } release_storage(); mStorage = const_cast<void*>(array); } else { return NULL; } } } else { void* array = editArrayImpl(); if (where != mCount) { const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize; void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; _do_move_forward(to, from, mCount - where); } } mCount = new_size; void* free_space = const_cast<void*>(itemLocation(where)); return free_space; }