void VectorImpl::_shrink(size_t where, size_t amount) { if (!mStorage) return; // ALOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d", // this, (int)where, (int)amount, (int)mCount, (int)capacity()); // ALOG_ASSERT(where + amount <= mCount, printf( "[%p] _shrink: where=%d, amount=%d, count=%d", this, (int)where, (int)amount, (int)mCount); // caller already checked const size_t new_size = mCount - amount; if (new_size*3 < capacity()) { const size_t new_capacity = max(kMinVectorCapacity, new_size*2); // ALOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity); if ((where == new_size) && (mFlags & HAS_TRIVIAL_COPY) && (mFlags & HAS_TRIVIAL_DTOR)) { const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage); SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize); mStorage = sb->data(); } else { SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize); if (sb) { void* array = sb->data(); if (where != 0) { _do_copy(array, mStorage, where); } if (where != new_size) { const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize; void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize; _do_copy(dest, from, new_size - where); } release_storage(); mStorage = const_cast<void*>(array); } } } else { void* array = editArrayImpl(); void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize; _do_destroy(to, amount); if (where != new_size) { const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; _do_move_backward(to, from, new_size - where); } } mCount = new_size; }
void* VectorImpl::editItemLocation(size_t index) { ALOG_ASSERT(index<capacity(), "[%p] editItemLocation: index=%d, capacity=%d, count=%d", this, (int)index, (int)capacity(), (int)mCount); if (index < capacity()) { void* buffer = editArrayImpl(); if (buffer) { return reinterpret_cast<char*>(buffer) + index*mItemSize; } } return 0; }
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, printf( "[%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); mStorage = sb->data(); } 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 { 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; }
void VectorImpl::_shrink(size_t where, size_t amount) { if (!mStorage) return; // ALOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d", // this, (int)where, (int)amount, (int)mCount, (int)capacity()); ALOG_ASSERT(where + amount <= mCount, "[%p] _shrink: 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_sub(&new_size, mCount, amount)); if (new_size < (capacity() / 2)) { // NOTE: (new_size * 2) is safe because capacity didn't overflow and // new_size < (capacity / 2)). const size_t new_capacity = max(kMinVectorCapacity, new_size * 2); // NOTE: (new_capacity * mItemSize), (where * mItemSize) and // ((where + amount) * mItemSize) beyond this point are safe because // we are always reducing the capacity of the underlying SharedBuffer. // In other words, (old_capacity * mItemSize) did not overflow, and // where < (where + amount) < new_capacity < old_capacity. if ((where == new_size) && (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; } } else { SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize); if (sb) { void* array = sb->data(); if (where != 0) { _do_copy(array, mStorage, where); } if (where != new_size) { const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize; void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize; _do_copy(dest, from, new_size - where); } release_storage(); mStorage = const_cast<void*>(array); } else{ return; } } } else { void* array = editArrayImpl(); void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize; _do_destroy(to, amount); if (where != new_size) { const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; _do_move_backward(to, from, new_size - where); } } mCount = new_size; }
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; }