ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const
{
    // binary search
    ssize_t err = NAME_NOT_FOUND;
    ssize_t l = 0;
    ssize_t h = size()-1;
    ssize_t mid;
    const void* a = arrayImpl();
    const size_t s = itemSize();
    while (l <= h) {
        mid = l + (h - l)/2;
        const void* const curr = reinterpret_cast<const char *>(a) + (mid*s);
        const int c = do_compare(curr, item);
        if (c == 0) {
            err = l = mid;
            break;
        } else if (c < 0) {
            l = mid + 1;
        } else {
            h = mid - 1;
        }
    }
    if (order) *order = l;
    return err;
}
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;
}
Example #3
0
const void* VectorImpl::itemLocation(size_t index) const
{
    ALOG_ASSERT(index<capacity(),
        "[%p] itemLocation: index=%d, capacity=%d, count=%d",
        this, (int)index, (int)capacity(), (int)mCount);

    const  void* buffer = arrayImpl();
    if (buffer)
        return reinterpret_cast<const char*>(buffer) + index*mItemSize;
    return 0;
}
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;
}