Exemple #1
0
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;
}
Exemple #3
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;
}