status_t VectorImpl::sort(VectorImpl::compar_r_t cmp, void* state) { // the sort must be stable. we're using insertion sort which // is well suited for small and already sorted arrays // for big arrays, it could be better to use mergesort const ssize_t count = size(); if (count > 1) { void* array = const_cast<void*>(arrayImpl()); void* temp = 0; ssize_t i = 1; while (i < count) { void* item = reinterpret_cast<char*>(array) + mItemSize*(i); void* curr = reinterpret_cast<char*>(array) + mItemSize*(i-1); if (cmp(curr, item, state) > 0) { if (!temp) { // we're going to have to modify the array... array = editArrayImpl(); if (!array) return NO_MEMORY; temp = malloc(mItemSize); if (!temp) return NO_MEMORY; item = reinterpret_cast<char*>(array) + mItemSize*(i); curr = reinterpret_cast<char*>(array) + mItemSize*(i-1); } else { _do_destroy(temp, 1); } _do_copy(temp, item, 1); ssize_t j = i-1; void* next = reinterpret_cast<char*>(array) + mItemSize*(i); do { _do_destroy(next, 1); _do_copy(next, curr, 1); next = curr; --j; curr = NULL; if (j >= 0) { curr = reinterpret_cast<char*>(array) + mItemSize*(j); } } while (j>=0 && (cmp(curr, temp, state) > 0)); _do_destroy(next, 1); _do_copy(next, temp, 1); } i++; } if (temp) { _do_destroy(temp, 1); free(temp); } } return NO_ERROR; }
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 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); 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::release_storage() { if (mStorage) { const SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage); if (sb->release(SharedBuffer::eKeepStorage) == 1) { _do_destroy(mStorage, mCount); SharedBuffer::dealloc(sb); } } }
void VectorImpl::_shrink(size_t where, size_t amount) { if (!mStorage) return; // LOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d", // this, (int)where, (int)amount, (int)mCount, (int)capacity()); if (where >= mCount) where = mCount - amount; const size_t new_size = mCount - amount; if (new_size*3 < capacity()) { const size_t new_capacity = max(kMinVectorCapacity, new_size*2); // LOGV("shrink vector %p, new_capacity=%d", this, (int)new_capacity); if ((where == mCount-amount) && (mFlags & HAS_TRIVIAL_COPY) && (mFlags & HAS_TRIVIAL_DTOR)) { const SharedBuffer* cur_sb = SharedBuffer::sharedBuffer(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 (mCount > where+amount) { 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, mCount-(where+amount)); } release_storage(); mStorage = const_cast<void*>(array); } } } else { void* array = editArrayImpl(); void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize; _do_destroy(to, amount); ssize_t s = mCount-(where+amount); if (s>0) { const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize; _do_move_backward(to, from, s); } } // adjust the number of items... mCount -= amount; }
ssize_t VectorImpl::replaceAt(const void* prototype, size_t index) { LOG_ASSERT(index<size(), "[%p] replace: index=%d, size=%d", this, (int)index, (int)size()); void* item = editItemLocation(index); if (item == 0) return NO_MEMORY; _do_destroy(item, 1); if (prototype == 0) { _do_construct(item, 1); } else { _do_copy(item, prototype, 1); } return ssize_t(index); }
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; }