Home | History | Annotate | Download | only in libutils
      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 
     34 namespace android {
     35 
     36 // ----------------------------------------------------------------------------
     37 
     38 const size_t kMinVectorCapacity = 4;
     39 
     40 static inline size_t max(size_t a, size_t b) {
     41     return a>b ? a : b;
     42 }
     43 
     44 // ----------------------------------------------------------------------------
     45 
     46 VectorImpl::VectorImpl(size_t itemSize, uint32_t flags)
     47     : mStorage(0), mCount(0), mFlags(flags), mItemSize(itemSize)
     48 {
     49 }
     50 
     51 VectorImpl::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 
     60 VectorImpl::~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 
     69 VectorImpl& 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 
     87 void* 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 
    108 size_t VectorImpl::capacity() const
    109 {
    110     if (mStorage) {
    111         return SharedBuffer::bufferFromData(mStorage)->size() / mItemSize;
    112     }
    113     return 0;
    114 }
    115 
    116 ssize_t VectorImpl::insertVectorAt(const VectorImpl& vector, size_t index)
    117 {
    118     return insertArrayAt(vector.arrayImpl(), index, vector.size());
    119 }
    120 
    121 ssize_t VectorImpl::appendVector(const VectorImpl& vector)
    122 {
    123     return insertVectorAt(vector, size());
    124 }
    125 
    126 ssize_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 
    137 ssize_t VectorImpl::appendArray(const void* array, size_t length)
    138 {
    139     return insertArrayAt(array, size(), length);
    140 }
    141 
    142 ssize_t VectorImpl::insertAt(size_t index, size_t numItems)
    143 {
    144     return insertAt(0, index, numItems);
    145 }
    146 
    147 ssize_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 
    162 static int sortProxy(const void* lhs, const void* rhs, void* func)
    163 {
    164     return (*(VectorImpl::compar_t)func)(lhs, rhs);
    165 }
    166 
    167 status_t VectorImpl::sort(VectorImpl::compar_t cmp)
    168 {
    169     return sort(sortProxy, (void*)cmp);
    170 }
    171 
    172 status_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 
    228 void VectorImpl::pop()
    229 {
    230     if (size())
    231         removeItemsAt(size()-1, 1);
    232 }
    233 
    234 void VectorImpl::push()
    235 {
    236     push(0);
    237 }
    238 
    239 void VectorImpl::push(const void* item)
    240 {
    241     insertAt(item, size());
    242 }
    243 
    244 ssize_t VectorImpl::add()
    245 {
    246     return add(0);
    247 }
    248 
    249 ssize_t VectorImpl::add(const void* item)
    250 {
    251     return insertAt(item, size());
    252 }
    253 
    254 ssize_t VectorImpl::replaceAt(size_t index)
    255 {
    256     return replaceAt(0, index);
    257 }
    258 
    259 ssize_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 
    282 ssize_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 
    294 void VectorImpl::finish_vector()
    295 {
    296     release_storage();
    297     mStorage = 0;
    298     mCount = 0;
    299 }
    300 
    301 void VectorImpl::clear()
    302 {
    303     _shrink(0, mCount);
    304 }
    305 
    306 void* 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 
    321 const 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 
    336 ssize_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 
    358 ssize_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 
    368 void 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 
    379 void* 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 
    454 void 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 
    520 size_t VectorImpl::itemSize() const {
    521     return mItemSize;
    522 }
    523 
    524 void VectorImpl::_do_construct(void* storage, size_t num) const
    525 {
    526     if (!(mFlags & HAS_TRIVIAL_CTOR)) {
    527         do_construct(storage, num);
    528     }
    529 }
    530 
    531 void VectorImpl::_do_destroy(void* storage, size_t num) const
    532 {
    533     if (!(mFlags & HAS_TRIVIAL_DTOR)) {
    534         do_destroy(storage, num);
    535     }
    536 }
    537 
    538 void 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 
    547 void VectorImpl::_do_splat(void* dest, const void* item, size_t num) const {
    548     do_splat(dest, item, num);
    549 }
    550 
    551 void VectorImpl::_do_move_forward(void* dest, const void* from, size_t num) const {
    552     do_move_forward(dest, from, num);
    553 }
    554 
    555 void VectorImpl::_do_move_backward(void* dest, const void* from, size_t num) const {
    556     do_move_backward(dest, from, num);
    557 }
    558 
    559 /*****************************************************************************/
    560 
    561 SortedVectorImpl::SortedVectorImpl(size_t itemSize, uint32_t flags)
    562     : VectorImpl(itemSize, flags)
    563 {
    564 }
    565 
    566 SortedVectorImpl::SortedVectorImpl(const VectorImpl& rhs)
    567 : VectorImpl(rhs)
    568 {
    569 }
    570 
    571 SortedVectorImpl::~SortedVectorImpl()
    572 {
    573 }
    574 
    575 SortedVectorImpl& SortedVectorImpl::operator = (const SortedVectorImpl& rhs)
    576 {
    577     return static_cast<SortedVectorImpl&>( VectorImpl::operator = (static_cast<const VectorImpl&>(rhs)) );
    578 }
    579 
    580 ssize_t SortedVectorImpl::indexOf(const void* item) const
    581 {
    582     return _indexOrderOf(item);
    583 }
    584 
    585 size_t SortedVectorImpl::orderOf(const void* item) const
    586 {
    587     size_t o;
    588     _indexOrderOf(item, &o);
    589     return o;
    590 }
    591 
    592 ssize_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 
    622 ssize_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 
    634 ssize_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 
    651 ssize_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 
    669 ssize_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