1/*
2 * Copyright (C) 2005 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "Vector"
18
19#include <string.h>
20#include <stdlib.h>
21#include <stdio.h>
22
23#include <cutils/log.h>
24#include <safe_iop.h>
25
26#include <utils/Errors.h>
27#include <utils/VectorImpl.h>
28
29#include "SharedBuffer.h"
30
31/*****************************************************************************/
32
33
34namespace android {
35
36// ----------------------------------------------------------------------------
37
38const size_t kMinVectorCapacity = 4;
39
40static inline size_t max(size_t a, size_t b) {
41    return a>b ? a : b;
42}
43
44// ----------------------------------------------------------------------------
45
46VectorImpl::VectorImpl(size_t itemSize, uint32_t flags)
47    : mStorage(0), mCount(0), mFlags(flags), mItemSize(itemSize)
48{
49}
50
51VectorImpl::VectorImpl(const VectorImpl& rhs)
52    :   mStorage(rhs.mStorage), mCount(rhs.mCount),
53        mFlags(rhs.mFlags), mItemSize(rhs.mItemSize)
54{
55    if (mStorage) {
56        SharedBuffer::bufferFromData(mStorage)->acquire();
57    }
58}
59
60VectorImpl::~VectorImpl()
61{
62    ALOGW_IF(mCount,
63        "[%p] subclasses of VectorImpl must call finish_vector()"
64        " in their destructor. Leaking %d bytes.",
65        this, (int)(mCount*mItemSize));
66    // We can't call _do_destroy() here because the vtable is already gone.
67}
68
69VectorImpl& VectorImpl::operator = (const VectorImpl& rhs)
70{
71    LOG_ALWAYS_FATAL_IF(mItemSize != rhs.mItemSize,
72        "Vector<> have different types (this=%p, rhs=%p)", this, &rhs);
73    if (this != &rhs) {
74        release_storage();
75        if (rhs.mCount) {
76            mStorage = rhs.mStorage;
77            mCount = rhs.mCount;
78            SharedBuffer::bufferFromData(mStorage)->acquire();
79        } else {
80            mStorage = 0;
81            mCount = 0;
82        }
83    }
84    return *this;
85}
86
87void* VectorImpl::editArrayImpl()
88{
89    if (mStorage) {
90        const SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage);
91        SharedBuffer* editable = sb->attemptEdit();
92        if (editable == 0) {
93            // If we're here, we're not the only owner of the buffer.
94            // We must make a copy of it.
95            editable = SharedBuffer::alloc(sb->size());
96            // Fail instead of returning a pointer to storage that's not
97            // editable. Otherwise we'd be editing the contents of a buffer
98            // for which we're not the only owner, which is undefined behaviour.
99            LOG_ALWAYS_FATAL_IF(editable == NULL);
100            _do_copy(editable->data(), mStorage, mCount);
101            release_storage();
102            mStorage = editable->data();
103        }
104    }
105    return mStorage;
106}
107
108size_t VectorImpl::capacity() const
109{
110    if (mStorage) {
111        return SharedBuffer::bufferFromData(mStorage)->size() / mItemSize;
112    }
113    return 0;
114}
115
116ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
117{
118    return insertArrayAt(vector.arrayImpl(), index, vector.size());
119}
120
121ssize_t VectorImpl::appendVector(const VectorImpl& vector)
122{
123    return insertVectorAt(vector, size());
124}
125
126ssize_t VectorImpl::insertArrayAt(const void* array, size_t index, size_t length)
127{
128    if (index > size())
129        return BAD_INDEX;
130    void* where = _grow(index, length);
131    if (where) {
132        _do_copy(where, array, length);
133    }
134    return where ? index : (ssize_t)NO_MEMORY;
135}
136
137ssize_t VectorImpl::appendArray(const void* array, size_t length)
138{
139    return insertArrayAt(array, size(), length);
140}
141
142ssize_t VectorImpl::insertAt(size_t index, size_t numItems)
143{
144    return insertAt(0, index, numItems);
145}
146
147ssize_t VectorImpl::insertAt(const void* item, size_t index, size_t numItems)
148{
149    if (index > size())
150        return BAD_INDEX;
151    void* where = _grow(index, numItems);
152    if (where) {
153        if (item) {
154            _do_splat(where, item, numItems);
155        } else {
156            _do_construct(where, numItems);
157        }
158    }
159    return where ? index : (ssize_t)NO_MEMORY;
160}
161
162static int sortProxy(const void* lhs, const void* rhs, void* func)
163{
164    return (*(VectorImpl::compar_t)func)(lhs, rhs);
165}
166
167status_t VectorImpl::sort(VectorImpl::compar_t cmp)
168{
169    return sort(sortProxy, (void*)cmp);
170}
171
172status_t VectorImpl::sort(VectorImpl::compar_r_t cmp, void* state)
173{
174    // the sort must be stable. we're using insertion sort which
175    // is well suited for small and already sorted arrays
176    // for big arrays, it could be better to use mergesort
177    const ssize_t count = size();
178    if (count > 1) {
179        void* array = const_cast<void*>(arrayImpl());
180        void* temp = 0;
181        ssize_t i = 1;
182        while (i < count) {
183            void* item = reinterpret_cast<char*>(array) + mItemSize*(i);
184            void* curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
185            if (cmp(curr, item, state) > 0) {
186
187                if (!temp) {
188                    // we're going to have to modify the array...
189                    array = editArrayImpl();
190                    if (!array) return NO_MEMORY;
191                    temp = malloc(mItemSize);
192                    if (!temp) return NO_MEMORY;
193                    item = reinterpret_cast<char*>(array) + mItemSize*(i);
194                    curr = reinterpret_cast<char*>(array) + mItemSize*(i-1);
195                } else {
196                    _do_destroy(temp, 1);
197                }
198
199                _do_copy(temp, item, 1);
200
201                ssize_t j = i-1;
202                void* next = reinterpret_cast<char*>(array) + mItemSize*(i);
203                do {
204                    _do_destroy(next, 1);
205                    _do_copy(next, curr, 1);
206                    next = curr;
207                    --j;
208                    curr = NULL;
209                    if (j >= 0) {
210                        curr = reinterpret_cast<char*>(array) + mItemSize*(j);
211                    }
212                } while (j>=0 && (cmp(curr, temp, state) > 0));
213
214                _do_destroy(next, 1);
215                _do_copy(next, temp, 1);
216            }
217            i++;
218        }
219
220        if (temp) {
221            _do_destroy(temp, 1);
222            free(temp);
223        }
224    }
225    return NO_ERROR;
226}
227
228void VectorImpl::pop()
229{
230    if (size())
231        removeItemsAt(size()-1, 1);
232}
233
234void VectorImpl::push()
235{
236    push(0);
237}
238
239void VectorImpl::push(const void* item)
240{
241    insertAt(item, size());
242}
243
244ssize_t VectorImpl::add()
245{
246    return add(0);
247}
248
249ssize_t VectorImpl::add(const void* item)
250{
251    return insertAt(item, size());
252}
253
254ssize_t VectorImpl::replaceAt(size_t index)
255{
256    return replaceAt(0, index);
257}
258
259ssize_t VectorImpl::replaceAt(const void* prototype, size_t index)
260{
261    ALOG_ASSERT(index<size(),
262        "[%p] replace: index=%d, size=%d", this, (int)index, (int)size());
263
264    if (index >= size()) {
265        return BAD_INDEX;
266    }
267
268    void* item = editItemLocation(index);
269    if (item != prototype) {
270        if (item == 0)
271            return NO_MEMORY;
272        _do_destroy(item, 1);
273        if (prototype == 0) {
274            _do_construct(item, 1);
275        } else {
276            _do_copy(item, prototype, 1);
277        }
278    }
279    return ssize_t(index);
280}
281
282ssize_t VectorImpl::removeItemsAt(size_t index, size_t count)
283{
284    ALOG_ASSERT((index+count)<=size(),
285        "[%p] remove: index=%d, count=%d, size=%d",
286               this, (int)index, (int)count, (int)size());
287
288    if ((index+count) > size())
289        return BAD_VALUE;
290   _shrink(index, count);
291   return index;
292}
293
294void VectorImpl::finish_vector()
295{
296    release_storage();
297    mStorage = 0;
298    mCount = 0;
299}
300
301void VectorImpl::clear()
302{
303    _shrink(0, mCount);
304}
305
306void* VectorImpl::editItemLocation(size_t index)
307{
308    ALOG_ASSERT(index<capacity(),
309        "[%p] editItemLocation: index=%d, capacity=%d, count=%d",
310        this, (int)index, (int)capacity(), (int)mCount);
311
312    if (index < capacity()) {
313        void* buffer = editArrayImpl();
314        if (buffer) {
315            return reinterpret_cast<char*>(buffer) + index*mItemSize;
316        }
317    }
318    return 0;
319}
320
321const void* VectorImpl::itemLocation(size_t index) const
322{
323    ALOG_ASSERT(index<capacity(),
324        "[%p] itemLocation: index=%d, capacity=%d, count=%d",
325        this, (int)index, (int)capacity(), (int)mCount);
326
327    if (index < capacity()) {
328        const  void* buffer = arrayImpl();
329        if (buffer) {
330            return reinterpret_cast<const char*>(buffer) + index*mItemSize;
331        }
332    }
333    return 0;
334}
335
336ssize_t VectorImpl::setCapacity(size_t new_capacity)
337{
338    // The capacity must always be greater than or equal to the size
339    // of this vector.
340    if (new_capacity <= size()) {
341        return capacity();
342    }
343
344    size_t new_allocation_size = 0;
345    LOG_ALWAYS_FATAL_IF(!safe_mul(&new_allocation_size, new_capacity, mItemSize));
346    SharedBuffer* sb = SharedBuffer::alloc(new_allocation_size);
347    if (sb) {
348        void* array = sb->data();
349        _do_copy(array, mStorage, size());
350        release_storage();
351        mStorage = const_cast<void*>(array);
352    } else {
353        return NO_MEMORY;
354    }
355    return new_capacity;
356}
357
358ssize_t VectorImpl::resize(size_t size) {
359    ssize_t result = NO_ERROR;
360    if (size > mCount) {
361        result = insertAt(mCount, size - mCount);
362    } else if (size < mCount) {
363        result = removeItemsAt(size, mCount - size);
364    }
365    return result < 0 ? result : size;
366}
367
368void VectorImpl::release_storage()
369{
370    if (mStorage) {
371        const SharedBuffer* sb = SharedBuffer::bufferFromData(mStorage);
372        if (sb->release(SharedBuffer::eKeepStorage) == 1) {
373            _do_destroy(mStorage, mCount);
374            SharedBuffer::dealloc(sb);
375        }
376    }
377}
378
379void* VectorImpl::_grow(size_t where, size_t amount)
380{
381//    ALOGV("_grow(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
382//        this, (int)where, (int)amount, (int)mCount, (int)capacity());
383
384    ALOG_ASSERT(where <= mCount,
385            "[%p] _grow: where=%d, amount=%d, count=%d",
386            this, (int)where, (int)amount, (int)mCount); // caller already checked
387
388    size_t new_size;
389    LOG_ALWAYS_FATAL_IF(!safe_add(&new_size, mCount, amount), "new_size overflow");
390
391    if (capacity() < new_size) {
392        // NOTE: This implementation used to resize vectors as per ((3*x + 1) / 2)
393        // (sigh..). Also note, the " + 1" was necessary to handle the special case
394        // where x == 1, where the resized_capacity will be equal to the old
395        // capacity without the +1. The old calculation wouldn't work properly
396        // if x was zero.
397        //
398        // This approximates the old calculation, using (x + (x/2) + 1) instead.
399        size_t new_capacity = 0;
400        LOG_ALWAYS_FATAL_IF(!safe_add(&new_capacity, new_size, (new_size / 2)),
401                            "new_capacity overflow");
402        LOG_ALWAYS_FATAL_IF(!safe_add(&new_capacity, new_capacity, static_cast<size_t>(1u)),
403                            "new_capacity overflow");
404        new_capacity = max(kMinVectorCapacity, new_capacity);
405
406        size_t new_alloc_size = 0;
407        LOG_ALWAYS_FATAL_IF(!safe_mul(&new_alloc_size, new_capacity, mItemSize),
408                            "new_alloc_size overflow");
409
410//        ALOGV("grow vector %p, new_capacity=%d", this, (int)new_capacity);
411        if ((mStorage) &&
412            (mCount==where) &&
413            (mFlags & HAS_TRIVIAL_COPY) &&
414            (mFlags & HAS_TRIVIAL_DTOR))
415        {
416            const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
417            SharedBuffer* sb = cur_sb->editResize(new_alloc_size);
418            if (sb) {
419                mStorage = sb->data();
420            } else {
421                return NULL;
422            }
423        } else {
424            SharedBuffer* sb = SharedBuffer::alloc(new_alloc_size);
425            if (sb) {
426                void* array = sb->data();
427                if (where != 0) {
428                    _do_copy(array, mStorage, where);
429                }
430                if (where != mCount) {
431                    const void* from = reinterpret_cast<const uint8_t *>(mStorage) + where*mItemSize;
432                    void* dest = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
433                    _do_copy(dest, from, mCount-where);
434                }
435                release_storage();
436                mStorage = const_cast<void*>(array);
437            } else {
438                return NULL;
439            }
440        }
441    } else {
442        void* array = editArrayImpl();
443        if (where != mCount) {
444            const void* from = reinterpret_cast<const uint8_t *>(array) + where*mItemSize;
445            void* to = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
446            _do_move_forward(to, from, mCount - where);
447        }
448    }
449    mCount = new_size;
450    void* free_space = const_cast<void*>(itemLocation(where));
451    return free_space;
452}
453
454void VectorImpl::_shrink(size_t where, size_t amount)
455{
456    if (!mStorage)
457        return;
458
459//    ALOGV("_shrink(this=%p, where=%d, amount=%d) count=%d, capacity=%d",
460//        this, (int)where, (int)amount, (int)mCount, (int)capacity());
461
462    ALOG_ASSERT(where + amount <= mCount,
463            "[%p] _shrink: where=%d, amount=%d, count=%d",
464            this, (int)where, (int)amount, (int)mCount); // caller already checked
465
466    size_t new_size;
467    LOG_ALWAYS_FATAL_IF(!safe_sub(&new_size, mCount, amount));
468
469    if (new_size < (capacity() / 2)) {
470        // NOTE: (new_size * 2) is safe because capacity didn't overflow and
471        // new_size < (capacity / 2)).
472        const size_t new_capacity = max(kMinVectorCapacity, new_size * 2);
473
474        // NOTE: (new_capacity * mItemSize), (where * mItemSize) and
475        // ((where + amount) * mItemSize) beyond this point are safe because
476        // we are always reducing the capacity of the underlying SharedBuffer.
477        // In other words, (old_capacity * mItemSize) did not overflow, and
478        // where < (where + amount) < new_capacity < old_capacity.
479        if ((where == new_size) &&
480            (mFlags & HAS_TRIVIAL_COPY) &&
481            (mFlags & HAS_TRIVIAL_DTOR))
482        {
483            const SharedBuffer* cur_sb = SharedBuffer::bufferFromData(mStorage);
484            SharedBuffer* sb = cur_sb->editResize(new_capacity * mItemSize);
485            if (sb) {
486                mStorage = sb->data();
487            } else {
488                return;
489            }
490        } else {
491            SharedBuffer* sb = SharedBuffer::alloc(new_capacity * mItemSize);
492            if (sb) {
493                void* array = sb->data();
494                if (where != 0) {
495                    _do_copy(array, mStorage, where);
496                }
497                if (where != new_size) {
498                    const void* from = reinterpret_cast<const uint8_t *>(mStorage) + (where+amount)*mItemSize;
499                    void* dest = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
500                    _do_copy(dest, from, new_size - where);
501                }
502                release_storage();
503                mStorage = const_cast<void*>(array);
504            } else{
505                return;
506            }
507        }
508    } else {
509        void* array = editArrayImpl();
510        void* to = reinterpret_cast<uint8_t *>(array) + where*mItemSize;
511        _do_destroy(to, amount);
512        if (where != new_size) {
513            const void* from = reinterpret_cast<uint8_t *>(array) + (where+amount)*mItemSize;
514            _do_move_backward(to, from, new_size - where);
515        }
516    }
517    mCount = new_size;
518}
519
520size_t VectorImpl::itemSize() const {
521    return mItemSize;
522}
523
524void VectorImpl::_do_construct(void* storage, size_t num) const
525{
526    if (!(mFlags & HAS_TRIVIAL_CTOR)) {
527        do_construct(storage, num);
528    }
529}
530
531void VectorImpl::_do_destroy(void* storage, size_t num) const
532{
533    if (!(mFlags & HAS_TRIVIAL_DTOR)) {
534        do_destroy(storage, num);
535    }
536}
537
538void VectorImpl::_do_copy(void* dest, const void* from, size_t num) const
539{
540    if (!(mFlags & HAS_TRIVIAL_COPY)) {
541        do_copy(dest, from, num);
542    } else {
543        memcpy(dest, from, num*itemSize());
544    }
545}
546
547void VectorImpl::_do_splat(void* dest, const void* item, size_t num) const {
548    do_splat(dest, item, num);
549}
550
551void VectorImpl::_do_move_forward(void* dest, const void* from, size_t num) const {
552    do_move_forward(dest, from, num);
553}
554
555void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) const {
556    do_move_backward(dest, from, num);
557}
558
559/*****************************************************************************/
560
561SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
562    : VectorImpl(itemSize, flags)
563{
564}
565
566SortedVectorImpl::SortedVectorImpl(const VectorImpl& rhs)
567: VectorImpl(rhs)
568{
569}
570
571SortedVectorImpl::~SortedVectorImpl()
572{
573}
574
575SortedVectorImpl& SortedVectorImpl::operator = (const SortedVectorImpl& rhs)
576{
577    return static_cast<SortedVectorImpl&>( VectorImpl::operator = (static_cast<const VectorImpl&>(rhs)) );
578}
579
580ssize_t SortedVectorImpl::indexOf(const void* item) const
581{
582    return _indexOrderOf(item);
583}
584
585size_t SortedVectorImpl::orderOf(const void* item) const
586{
587    size_t o;
588    _indexOrderOf(item, &o);
589    return o;
590}
591
592ssize_t SortedVectorImpl::_indexOrderOf(const void* item, size_t* order) const
593{
594    if (order) *order = 0;
595    if (isEmpty()) {
596        return NAME_NOT_FOUND;
597    }
598    // binary search
599    ssize_t err = NAME_NOT_FOUND;
600    ssize_t l = 0;
601    ssize_t h = size()-1;
602    ssize_t mid;
603    const void* a = arrayImpl();
604    const size_t s = itemSize();
605    while (l <= h) {
606        mid = l + (h - l)/2;
607        const void* const curr = reinterpret_cast<const char *>(a) + (mid*s);
608        const int c = do_compare(curr, item);
609        if (c == 0) {
610            err = l = mid;
611            break;
612        } else if (c < 0) {
613            l = mid + 1;
614        } else {
615            h = mid - 1;
616        }
617    }
618    if (order) *order = l;
619    return err;
620}
621
622ssize_t SortedVectorImpl::add(const void* item)
623{
624    size_t order;
625    ssize_t index = _indexOrderOf(item, &order);
626    if (index < 0) {
627        index = VectorImpl::insertAt(item, order, 1);
628    } else {
629        index = VectorImpl::replaceAt(item, index);
630    }
631    return index;
632}
633
634ssize_t SortedVectorImpl::merge(const VectorImpl& vector)
635{
636    // naive merge...
637    if (!vector.isEmpty()) {
638        const void* buffer = vector.arrayImpl();
639        const size_t is = itemSize();
640        size_t s = vector.size();
641        for (size_t i=0 ; i<s ; i++) {
642            ssize_t err = add( reinterpret_cast<const char*>(buffer) + i*is );
643            if (err<0) {
644                return err;
645            }
646        }
647    }
648    return NO_ERROR;
649}
650
651ssize_t SortedVectorImpl::merge(const SortedVectorImpl& vector)
652{
653    // we've merging a sorted vector... nice!
654    ssize_t err = NO_ERROR;
655    if (!vector.isEmpty()) {
656        // first take care of the case where the vectors are sorted together
657        if (do_compare(vector.itemLocation(vector.size()-1), arrayImpl()) <= 0) {
658            err = VectorImpl::insertVectorAt(static_cast<const VectorImpl&>(vector), 0);
659        } else if (do_compare(vector.arrayImpl(), itemLocation(size()-1)) >= 0) {
660            err = VectorImpl::appendVector(static_cast<const VectorImpl&>(vector));
661        } else {
662            // this could be made a little better
663            err = merge(static_cast<const VectorImpl&>(vector));
664        }
665    }
666    return err;
667}
668
669ssize_t SortedVectorImpl::remove(const void* item)
670{
671    ssize_t i = indexOf(item);
672    if (i>=0) {
673        VectorImpl::removeItemsAt(i, 1);
674    }
675    return i;
676}
677
678/*****************************************************************************/
679
680}; // namespace android
681
682